Annotation of Net2/kern/vfs_bio.c, revision 1.1.1.2

1.1.1.2 ! root        1: /* 
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 1992 Carnegie Mellon University
        !             4:  * All Rights Reserved.
        !             5:  * 
        !             6:  * Permission to use, copy, modify and distribute this software and its
        !             7:  * documentation is hereby granted, provided that both the copyright
        !             8:  * notice and this permission notice appear in all copies of the
        !             9:  * software, derivative works or modified versions, and any portions
        !            10:  * thereof, and that both notices appear in supporting documentation.
        !            11:  * 
        !            12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
        !            14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            15:  * 
        !            16:  * Carnegie Mellon requests users of this software to return to
        !            17:  * 
        !            18:  *  Software Distribution Coordinator  or  [email protected]
        !            19:  *  School of Computer Science
        !            20:  *  Carnegie Mellon University
        !            21:  *  Pittsburgh PA 15213-3890
        !            22:  * 
        !            23:  * any improvements or extensions that they make and grant Carnegie Mellon 
        !            24:  * the rights to redistribute these changes.
        !            25:  */
        !            26: /*
        !            27:  *     vfs_bio.c,v 1.1.2.2 1993/08/07 01:56:01 cgd Exp
        !            28:  *
        !            29:  * (Mach) HISTORY
        !            30:  * Revision 2.3  92/07/08  16:19:50  mrt
        !            31:  *     Added fourth arg, TRUE, to vm_allocate call in getnewbuf.
        !            32:  *     [92/07/02            mrt]
        !            33:  * 
        !            34:  * Revision 2.2  92/06/25  17:25:40  mrt
        !            35:  *     Clear b_resid on release.  No one cares once released.
        !            36:  *             [ XXX -- this had to be squished; symlinks care -- cgd]
        !            37:  *     [92/06/25            rwd]
        !            38:  *     Set b_rcred before VOP_STRATEGY calls. [from Jolitz]
        !            39:  * 
        !            40:  * Revision 2.1  92/04/21  17:12:36  rwd
        !            41:  * BSDSS
        !            42:  */
        !            43: 
1.1       root       44: /*
                     45:  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
                     46:  * All rights reserved.
                     47:  *
                     48:  * Redistribution and use in source and binary forms, with or without
                     49:  * modification, are permitted provided that the following conditions
                     50:  * are met:
                     51:  * 1. Redistributions of source code must retain the above copyright
                     52:  *    notice, this list of conditions and the following disclaimer.
                     53:  * 2. Redistributions in binary form must reproduce the above copyright
                     54:  *    notice, this list of conditions and the following disclaimer in the
                     55:  *    documentation and/or other materials provided with the distribution.
                     56:  * 3. All advertising materials mentioning features or use of this software
                     57:  *    must display the following acknowledgement:
                     58:  *     This product includes software developed by the University of
                     59:  *     California, Berkeley and its contributors.
                     60:  * 4. Neither the name of the University nor the names of its contributors
                     61:  *    may be used to endorse or promote products derived from this software
                     62:  *    without specific prior written permission.
                     63:  *
                     64:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     65:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     66:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     67:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     68:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     69:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     70:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     71:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     72:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     73:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     74:  * SUCH DAMAGE.
                     75:  *
                     76:  *     from: @(#)vfs_bio.c     7.40 (Berkeley) 5/8/91
                     77:  */
                     78: 
1.1.1.2 ! root       79: #include <sys/param.h>
        !            80: #include <sys/proc.h>
        !            81: #include <sys/buf.h>
        !            82: #include <sys/vnode.h>
        !            83: #include <sys/specdev.h>
        !            84: #include <sys/mount.h>
        !            85: #include <sys/trace.h>
        !            86: #include <sys/resourcevar.h>
        !            87: #include <vm/vm.h>
        !            88: #include <vm/vm_param.h>
        !            89: 
        !            90: int debug_bio = 0;
        !            91: int freebufspace = 0;
        !            92: int allocbufspace = 0;
        !            93: extern int bufpages;
        !            94: 
        !            95: static struct  buf *getnewbuf  __P((int));
        !            96: extern vm_map_t        buffer_map;
        !            97: 
        !            98: struct buf     *buf;                   /* the buffer pool itself */
        !            99: char           *buffers;
        !           100: int            nbuf;                   /* number of buffer headers */
        !           101: int            bufpages;        /* number of memory pages in the buffer pool */
        !           102: struct buf     *swbuf;               /* swap I/O headers (XXX go elsewhere?) */
        !           103: int            nswbuf;
        !           104: struct bufhd   bufhash[BUFHSZ];        /* heads of hash lists */
        !           105: struct buf     bfreelist[BQUEUES];     /* heads of available lists */
        !           106: struct buf     bswlist;                /* head of free swap header list */
        !           107: struct buf     *bclnlist;              /* head of cleaned page list */
1.1       root      108: 
                    109: /*
                    110:  * Initialize buffers and hash links for buffers.
                    111:  */
1.1.1.2 ! root      112: void
1.1       root      113: bufinit()
                    114: {
1.1.1.2 ! root      115:     struct bufhd *bh;
        !           116:     struct buf *bp;
1.1       root      117: 
1.1.1.2 ! root      118:     freebufspace = bufpages * NBPG;
        !           119: 
        !           120:     /* first, make a null hash table */
        !           121:     for(bh = bufhash; bh < bufhash + BUFHSZ; bh++) {
        !           122:        bh->b_flags = 0;
        !           123:        bh->b_forw = (struct buf *)bh;
        !           124:        bh->b_back = (struct buf *)bh;
        !           125:     }
        !           126: 
        !           127:     /* next, make a null set of free lists */
        !           128:     for(bp = bfreelist; bp < bfreelist + BQUEUES; bp++) {
        !           129:        bp->b_flags = 0;
        !           130:        bp->av_forw = bp;
        !           131:        bp->av_back = bp;
        !           132:        bp->b_forw = bp;
        !           133:        bp->b_back = bp;
        !           134: 
        !           135:     }
        !           136: 
        !           137:     /* finally, initialize each buffer header and stick on empty q */
        !           138:     for(bp = buf; bp < buf + nbuf ; bp++) {
        !           139:        bp->b_flags = B_HEAD | B_INVAL; /* we're just an empty header */
        !           140:        bp->b_dev = NODEV;
        !           141:        bp->b_rcred = bp->b_wcred = NOCRED;
        !           142:        bp->b_vp = 0;
        !           143:        binstailfree(bp, bfreelist + BQ_EMPTY);
        !           144:        binshash(bp, bfreelist + BQ_EMPTY);
        !           145:     }
1.1       root      146: }
                    147: 
1.1.1.2 ! root      148: 
1.1       root      149: /*
                    150:  * Find the block in the buffer pool.
                    151:  * If the buffer is not present, allocate a new buffer and load
                    152:  * its contents according to the filesystem fill routine.
                    153:  */
1.1.1.2 ! root      154: int
1.1       root      155: bread(vp, blkno, size, cred, bpp)
                    156:        struct vnode *vp;
                    157:        daddr_t blkno;
                    158:        int size;
                    159:        struct ucred *cred;
                    160:        struct buf **bpp;
                    161: {
1.1.1.2 ! root      162:        struct buf *bp;
        !           163:        int rv = 0;
1.1       root      164: 
1.1.1.2 ! root      165:        bp = getblk (vp, blkno, size);
        !           166: 
        !           167:        /* if not found in cache, do some I/O */
        !           168:        if ((bp->b_flags & B_CACHE) == 0 || (bp->b_flags & B_INVAL) != 0) {
        !           169:                bp->b_flags |= B_READ;
        !           170:                bp->b_flags &= ~(B_DONE|B_ERROR|B_INVAL);
        !           171:                if (cred != NOCRED && bp->b_rcred == NOCRED) {
        !           172:                        crhold(cred);
        !           173:                        bp->b_rcred = cred;
        !           174:                }
        !           175:                VOP_STRATEGY(bp);
        !           176:                rv = biowait (bp);
        !           177:        }
        !           178:        *bpp = bp;
        !           179:        
        !           180:        return (rv);
1.1       root      181: }
                    182: 
                    183: /*
                    184:  * Operates like bread, but also starts I/O on the specified
1.1.1.2 ! root      185:  * read-ahead block. [See page 55 of Bach's Book]
1.1       root      186:  */
1.1.1.2 ! root      187: int
1.1       root      188: breada(vp, blkno, size, rablkno, rabsize, cred, bpp)
                    189:        struct vnode *vp;
1.1.1.2 ! root      190:        daddr_t blkno; 
        !           191:        int size;
        !           192:        daddr_t rablkno; 
        !           193:        int rabsize;
1.1       root      194:        struct ucred *cred;
                    195:        struct buf **bpp;
                    196: {
1.1.1.2 ! root      197:        struct buf *bp, *rabp;
        !           198:        int rv = 0, needwait = 0;
1.1       root      199: 
1.1.1.2 ! root      200:        bp = getblk (vp, blkno, size);
        !           201: 
        !           202:        /* if not found in cache, do some I/O */
        !           203:        if ((bp->b_flags & B_CACHE) == 0 || (bp->b_flags & B_INVAL) != 0) {
        !           204:                bp->b_flags |= B_READ;
        !           205:                bp->b_flags &= ~(B_DONE|B_ERROR|B_INVAL);
        !           206:                if (cred != NOCRED && bp->b_rcred == NOCRED) {
        !           207:                        crhold(cred);
        !           208:                        bp->b_rcred = cred;
        !           209:                }
        !           210:                VOP_STRATEGY(bp);
        !           211:                needwait++;
        !           212:        }
        !           213:        
        !           214:        rabp = getblk (vp, rablkno, rabsize);
        !           215: 
        !           216:        /* if not found in cache, do some I/O (overlapped with first) */
        !           217:        if ((rabp->b_flags & B_CACHE) == 0 || (rabp->b_flags & B_INVAL) != 0) {
        !           218:                rabp->b_flags |= B_READ | B_ASYNC;
        !           219:                rabp->b_flags &= ~(B_DONE|B_ERROR|B_INVAL);
        !           220:                if (cred != NOCRED && bp->b_rcred  == NOCRED) {
        !           221:                        crhold(cred);
        !           222:                        rabp->b_rcred = cred;
        !           223:                }
        !           224:                VOP_STRATEGY(rabp);
        !           225:        } else
        !           226:                brelse(rabp);
        !           227:        
        !           228:        /* wait for original I/O */
        !           229:        if (needwait)
        !           230:                rv = biowait (bp);
        !           231: 
        !           232:        *bpp = bp;
        !           233:        return (rv);
1.1       root      234: }
                    235: 
                    236: /*
                    237:  * Synchronous write.
                    238:  * Release buffer on completion.
                    239:  */
1.1.1.2 ! root      240: int
1.1       root      241: bwrite(bp)
                    242:        register struct buf *bp;
                    243: {
1.1.1.2 ! root      244:        int rv;
1.1       root      245: 
1.1.1.2 ! root      246:        if(bp->b_flags & B_INVAL) {
        !           247:                brelse(bp);
        !           248:                return (0);
        !           249:        } else {
        !           250:                int wasdelayed;
        !           251: 
        !           252:                if(!(bp->b_flags & B_BUSY))
        !           253:                        panic("bwrite: not busy");
        !           254: 
        !           255:                wasdelayed = bp->b_flags & B_DELWRI;
        !           256:                bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_ASYNC|B_DELWRI);
        !           257:                if(wasdelayed) 
        !           258:                        reassignbuf(bp, bp->b_vp);
        !           259: 
        !           260:                bp->b_flags |= B_DIRTY;
        !           261:                bp->b_vp->v_numoutput++;
        !           262:                VOP_STRATEGY(bp);
        !           263:                rv = biowait(bp);
        !           264:                if (!rv)
        !           265:                        bp->b_flags &= ~B_DIRTY;
        !           266:                brelse(bp);
        !           267:                return (rv);
        !           268:        }
1.1       root      269: }
                    270: 
                    271: /*
                    272:  * Delayed write.
                    273:  *
                    274:  * The buffer is marked dirty, but is not queued for I/O.
                    275:  * This routine should be used when the buffer is expected
                    276:  * to be modified again soon, typically a small write that
                    277:  * partially fills a buffer.
                    278:  *
                    279:  * NB: magnetic tapes cannot be delayed; they must be
                    280:  * written in the order that the writes are requested.
                    281:  */
1.1.1.2 ! root      282: void 
1.1       root      283: bdwrite(bp)
                    284:        register struct buf *bp;
                    285: {
                    286: 
1.1.1.2 ! root      287:        if(!(bp->b_flags & B_BUSY))
        !           288:                panic("bdwrite: not busy");
        !           289: 
        !           290:        if(bp->b_flags & B_INVAL) {
        !           291:                brelse(bp);
        !           292:                return;
        !           293:        }
        !           294:        if(bp->b_flags & B_TAPE) {
        !           295:                bwrite(bp);
        !           296:                return;
        !           297:        }
        !           298:        bp->b_flags &= ~(B_READ|B_DONE);
        !           299:        bp->b_flags |= B_DIRTY|B_DELWRI;
        !           300:        reassignbuf(bp, bp->b_vp);
        !           301:        brelse(bp);
1.1       root      302:        return;
                    303: }
                    304: 
                    305: /*
                    306:  * Asynchronous write.
                    307:  * Start I/O on a buffer, but do not wait for it to complete.
                    308:  * The buffer is released when the I/O completes.
                    309:  */
1.1.1.2 ! root      310: void
1.1       root      311: bawrite(bp)
                    312:        register struct buf *bp;
                    313: {
                    314: 
1.1.1.2 ! root      315:        if(!(bp->b_flags & B_BUSY))
        !           316:                panic("bawrite: not busy");
        !           317: 
        !           318:        if(bp->b_flags & B_INVAL)
        !           319:                brelse(bp);
        !           320:        else {
        !           321:                int wasdelayed;
        !           322: 
        !           323:                wasdelayed = bp->b_flags & B_DELWRI;
        !           324:                bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
        !           325:                if(wasdelayed) 
        !           326:                        reassignbuf(bp, bp->b_vp);
        !           327: 
        !           328:                bp->b_flags |= B_DIRTY | B_ASYNC;
        !           329:                bp->b_vp->v_numoutput++;
        !           330:                VOP_STRATEGY(bp);
        !           331:        }
1.1       root      332: }
                    333: 
                    334: /*
                    335:  * Release a buffer.
                    336:  * Even if the buffer is dirty, no I/O is started.
                    337:  */
1.1.1.2 ! root      338: void
1.1       root      339: brelse(bp)
                    340:        register struct buf *bp;
                    341: {
1.1.1.2 ! root      342:        int x;
1.1       root      343: 
1.1.1.2 ! root      344:        /* anyone need a "free" block? */
        !           345:        x=splbio();
        !           346:        if ((bfreelist + BQ_AGE)->b_flags & B_WANTED) {
        !           347:                (bfreelist + BQ_AGE) ->b_flags &= ~B_WANTED;
        !           348:                wakeup(bfreelist);
        !           349:        }
        !           350:        /* anyone need this very block? */
        !           351:        if (bp->b_flags & B_WANTED) {
        !           352:                bp->b_flags &= ~B_WANTED;
        !           353:                wakeup(bp);
        !           354:        }
        !           355: 
        !           356:        if (bp->b_flags & (B_INVAL|B_ERROR)) {
        !           357:                bp->b_flags |= B_INVAL;
        !           358:                bp->b_flags &= ~(B_DELWRI|B_CACHE);
        !           359:                if(bp->b_vp)
        !           360:                        brelvp(bp);
        !           361:        }
        !           362: 
        !           363:        /* enqueue */
        !           364:        /* just an empty buffer head ... */
        !           365:        /*if(bp->b_flags & B_HEAD)
        !           366:                binsheadfree(bp, bfreelist + BQ_EMPTY)*/
        !           367:        /* buffers with junk contents */
        !           368:        /*else*/ if(bp->b_flags & (B_ERROR|B_INVAL|B_NOCACHE))
        !           369:                binsheadfree(bp, bfreelist + BQ_AGE)
        !           370:        /* buffers with stale but valid contents */
        !           371:        else if(bp->b_flags & B_AGE)
        !           372:                binstailfree(bp, bfreelist + BQ_AGE)
        !           373:        /* buffers with valid and quite potentially reuseable contents */
        !           374:        else
        !           375:                binstailfree(bp, bfreelist + BQ_LRU)
        !           376: 
        !           377:        /* unlock */
        !           378:        bp->b_flags &= ~B_BUSY;
        !           379:        /* bp->b_resid = 0; XXX (cgd) -- actually, we need resid for symlinks */
        !           380:        splx(x);
        !           381: }
        !           382: 
        !           383: /*
        !           384:  * Find a buffer which is available for use.
        !           385:  * If free memory for buffer space and an empty header from the empty list,
        !           386:  * use that. Otherwise, select something from a free list.
        !           387:  * Preference is to AGE list, then LRU list.
        !           388:  */
        !           389: static struct buf *
        !           390: getnewbuf(sz)
        !           391:     int sz;
        !           392: {
        !           393:        struct buf *bp;
        !           394:        int x, allocsize;
        !           395: 
        !           396:        x = splbio();
        !           397:        allocsize = MAXBSIZE;  /* XXX -- should be round_page(sz) */
        !           398: 
        !           399: start:
        !           400:        /* can we constitute a new buffer? */
        !           401:        if (freebufspace >= allocsize
        !           402:                && bfreelist[BQ_EMPTY].av_forw != (struct buf *)bfreelist+BQ_EMPTY) {
        !           403:                caddr_t addr;
        !           404:                int kr;
        !           405: 
        !           406: #if 0
        !           407:                if ((kr = vm_allocate(buffer_map, (vm_offset_t *)  &addr, (vm_size_t) allocsize, TRUE))
        !           408:                    != KERN_SUCCESS) goto tryfree;
        !           409: #else
        !           410:                if (! (addr = (caddr_t) kmem_alloc (buffer_map, (vm_size_t) allocsize))) goto tryfree;
        !           411: #endif
        !           412:                freebufspace -= allocsize;
        !           413:                allocbufspace += allocsize;
        !           414: 
        !           415:                bp = bfreelist[BQ_EMPTY].av_forw;
        !           416:                if (debug_bio) printf("   allocate bp: %x addr: %x (alloc)size: %x\n",bp, addr, allocsize);
        !           417:                bp->b_flags = B_BUSY | B_INVAL;
        !           418:                bremfree(bp);
        !           419:                bp->b_un.b_addr = (caddr_t) addr;
        !           420:                bp->b_bufsize = allocsize;
        !           421:                goto fillin;
        !           422:        }
        !           423: 
        !           424: tryfree:
        !           425:        if (bfreelist[BQ_AGE].av_forw != (struct buf *)bfreelist+BQ_AGE) {
        !           426:                bp = bfreelist[BQ_AGE].av_forw;
        !           427:                bremfree(bp);
        !           428:        } else if (bfreelist[BQ_LRU].av_forw != (struct buf *)bfreelist+BQ_LRU) {
        !           429:                bp = bfreelist[BQ_LRU].av_forw;
        !           430:                bremfree(bp);
        !           431:        } else  {
        !           432:                /* wait for a free buffer of any kind */
        !           433:                (bfreelist + BQ_AGE)->b_flags |= B_WANTED;
        !           434:                tsleep(bfreelist, PRIBIO, "getnewbuf", 0);
        !           435:                splx(x);
        !           436:                return (0);
        !           437:        }
        !           438: 
        !           439:        /* if we are a delayed write, convert to an async write! */
        !           440:        if (bp->b_flags & B_DELWRI) {
        !           441:                bp->b_flags |= B_BUSY;
        !           442:                bawrite (bp);
        !           443:                goto start;
        !           444:        }
        !           445: 
        !           446: 
        !           447:        if(bp->b_vp)
        !           448:                brelvp(bp);
        !           449: 
        !           450:        /* we are not free, nor do we contain interesting data */
        !           451:        if (bp->b_rcred != NOCRED)
        !           452:                crfree(bp->b_rcred);
        !           453:        if (bp->b_wcred != NOCRED)
        !           454:                crfree(bp->b_wcred);
        !           455: 
        !           456:        bp->b_flags = B_BUSY;
        !           457: fillin:
        !           458:        bremhash(bp);
        !           459:        splx(x);
        !           460:        bp->b_dev = NODEV;
        !           461:        bp->b_vp = NULL;
        !           462:        bp->b_blkno = bp->b_lblkno = 0;
        !           463:        bp->b_iodone = 0;
        !           464:        bp->b_error = 0;
        !           465:        bp->b_resid = 0;
        !           466:        bp->b_wcred = bp->b_rcred = NOCRED;
        !           467:        if (bp->b_bufsize != allocsize)
        !           468:                allocbuf(bp, allocsize);
        !           469:        bp->b_bcount = sz;
        !           470:        bp->b_dirtyoff = bp->b_dirtyend = 0;
        !           471:        return (bp);
1.1       root      472: }
                    473: 
                    474: /*
                    475:  * Check to see if a block is currently memory resident.
1.1.1.2 ! root      476:  * This routine must be called at splbio().  If it is not,
        !           477:  * and you take a disk interrupt while in the while loop,
        !           478:  * you can loop forever.
1.1       root      479:  */
1.1.1.2 ! root      480: struct buf *
1.1       root      481: incore(vp, blkno)
                    482:        struct vnode *vp;
                    483:        daddr_t blkno;
                    484: {
1.1.1.2 ! root      485:        struct buf *bh;
        !           486:        struct buf *bp;
        !           487: 
        !           488:        bh = BUFHASH(vp, blkno);
1.1       root      489: 
1.1.1.2 ! root      490:        /* Search hash chain */
        !           491:        bp = bh->b_forw;
        !           492:        while (bp != (struct buf *) bh) {
        !           493:                /* hit */
        !           494:                if (bp->b_lblkno == blkno && bp->b_vp == vp
        !           495:                        && (bp->b_flags & B_INVAL) == 0)
        !           496:                        return (bp);
        !           497:                bp = bp->b_forw;
        !           498:        }
        !           499:        
        !           500:        return(0);
1.1       root      501: }
                    502: 
                    503: /*
1.1.1.2 ! root      504:  * Get a block of requested size that is associated with
        !           505:  * a given vnode and block offset. If it is found in the
        !           506:  * block cache, mark it as having been found, make it busy
        !           507:  * and return it. Otherwise, return an empty block of the
        !           508:  * correct size. It is up to the caller to insure that the
        !           509:  * cached blocks be of the correct size.
1.1       root      510:  */
                    511: struct buf *
                    512: getblk(vp, blkno, size)
                    513:        register struct vnode *vp;
                    514:        daddr_t blkno;
                    515:        int size;
                    516: {
1.1.1.2 ! root      517:        struct buf *bp, *bh;
        !           518:        int x;
1.1       root      519: 
1.1.1.2 ! root      520:        x = splbio();
        !           521: start:
        !           522:        if (bp = incore(vp, blkno)) {
        !           523:                if (bp->b_flags & B_BUSY) {
        !           524:                        bp->b_flags |= B_WANTED;
        !           525:                        tsleep (bp, PRIBIO, "getblk", 0);
        !           526:                        goto start;
        !           527:                }
        !           528:                bp->b_flags |= B_BUSY | B_CACHE;
        !           529:                bremfree(bp);
        !           530:                if (size > bp->b_bufsize)
        !           531:                        panic("getblk: buffer too small"); /* XXX */
        !           532:                /* if (bp->b_bufsize != size) allocbuf(bp, size); */
        !           533:        } else {
        !           534:                splx(x);
        !           535:                if((bp = getnewbuf(size)) == NULL) {
        !           536:                        x = splbio();
        !           537:                        goto start;
        !           538:                }
        !           539:                bp->b_blkno = bp->b_lblkno = blkno;
        !           540:                bgetvp(vp, bp);
        !           541:                x = splbio();
        !           542:                bh = BUFHASH(vp, blkno);
        !           543:                binshash(bp, bh);
        !           544:                bp->b_flags = B_BUSY;
        !           545:        }
        !           546:        splx(x);
        !           547:        return (bp);
1.1       root      548: }
                    549: 
                    550: /*
1.1.1.2 ! root      551:  * Get an empty, disassociated buffer of given size.
1.1       root      552:  */
                    553: struct buf *
                    554: geteblk(size)
                    555:        int size;
                    556: {
1.1.1.2 ! root      557:        struct buf *bp;
        !           558:        int x;
1.1       root      559: 
1.1.1.2 ! root      560:        while ((bp = getnewbuf(size)) == 0)
        !           561:                ;
        !           562:        x = splbio();
        !           563:        binshash(bp, bfreelist + BQ_AGE);
        !           564:        splx(x);
1.1       root      565: 
1.1.1.2 ! root      566:        return (bp);
1.1       root      567: }
                    568: 
                    569: /*
1.1.1.2 ! root      570:  * Exchange a buffer's underlying buffer storage for one of different
        !           571:  * size, taking care to maintain contents appropriately. When buffer
        !           572:  * increases in size, caller is responsible for filling out additional
        !           573:  * contents. When buffer shrinks in size, data is lost, so caller must
        !           574:  * first return it to backing store before shrinking the buffer, as
        !           575:  * no implied I/O will be done.
1.1       root      576:  */
1.1.1.2 ! root      577: void
        !           578: allocbuf(bp, size)
        !           579:        register struct buf *bp;
        !           580:        int size;
1.1       root      581: {
1.1.1.2 ! root      582:        vm_size_t       current_size, desired_size;
        !           583:        vm_offset_t     new_start;
        !           584:        int             kr;
        !           585: 
        !           586:        current_size = bp->b_bufsize;
        !           587:        desired_size = MAXBSIZE; /* XXX (cgd) -- round_page(size) */
        !           588: 
        !           589:        if (current_size < desired_size) {
        !           590:            /*
        !           591:             * Buffer is growing.
        !           592:             * If buffer already has data, allocate new area and copy
        !           593:             * old data to it.
        !           594:             */
        !           595: #if 0
        !           596:            kr = vm_allocate(buffer_map,
        !           597:                             &new_start,
        !           598:                             desired_size,
        !           599:                             TRUE);
        !           600:            if (kr != KERN_SUCCESS)
        !           601: #else
        !           602:            new_start = kmem_alloc (buffer_map, desired_size);
        !           603:            if (! new_start)
        !           604: #endif
        !           605:                panic("allocbuf: allocate",kr);
        !           606:            if (debug_bio) printf(" reallocate bp: %x addr: %x size: %x\n",bp, new_start, desired_size);
        !           607:            if (current_size) {
        !           608:                bcopy(bp->b_un.b_addr,
        !           609:                      (caddr_t) new_start,
        !           610:                      bp->b_bufsize);
        !           611: #if 0
        !           612:                kr = vm_deallocate(buffer_map,
        !           613:                                   (vm_offset_t)bp->b_un.b_addr,
        !           614:                                   current_size);
        !           615:                if (kr != KERN_SUCCESS)
        !           616:                    panic("allocbuf: deallocate",kr);
        !           617: #else
        !           618:                kmem_free (buffer_map, (vm_offset_t)bp->b_un.b_addr, current_size);
        !           619: #endif
        !           620:                if (debug_bio) printf(" deallocate bp: %x addr: %x size: %x\n",bp, bp->b_un.b_addr,bp->b_bufsize);
        !           621:            }
        !           622:            bp->b_un.b_addr = (char *)new_start;
        !           623:            bp->b_bufsize = desired_size;
        !           624: 
        !           625:            /* adjust buffer cache's idea of memory allocated to buffer contents */
        !           626:            freebufspace -= desired_size - current_size;
        !           627:            allocbufspace += desired_size - current_size;
        !           628:        }
1.1       root      629: 
1.1.1.2 ! root      630:        bp->b_bcount = size;
1.1       root      631: }
                    632: 
                    633: /*
1.1.1.2 ! root      634:  * Patiently await operations to complete on this buffer.
        !           635:  * When they do, extract error value and return it.
1.1       root      636:  * Extract and return any errors associated with the I/O.
1.1.1.2 ! root      637:  * If an invalid block, force it off the lookup hash chains.
1.1       root      638:  */
1.1.1.2 ! root      639: int
1.1       root      640: biowait(bp)
                    641:        register struct buf *bp;
                    642: {
1.1.1.2 ! root      643:        int x;
1.1       root      644: 
1.1.1.2 ! root      645:        x = splbio();
        !           646:        while ((bp->b_flags & B_DONE) == 0)
        !           647:                tsleep((caddr_t)bp, PRIBIO, "biowait", 0);
        !           648:        if((bp->b_flags & B_ERROR) || bp->b_error) {
        !           649:                if ((bp->b_flags & B_INVAL) == 0) {
        !           650:                        bp->b_flags |= B_INVAL;
        !           651: /* XXX
        !           652:  * brelse() already puts buffers with B_ERROR set on the age queue
        !           653:  *     and i believe it's wrong to let bp->b_error override B_ERROR
        !           654:  *     but it certainly appears to work OK this way...
        !           655:  */    
        !           656:                        bremhash(bp);
        !           657:                        binshash(bp, bfreelist + BQ_AGE);
        !           658:                }
        !           659:                if (!bp->b_error)
        !           660:                        bp->b_error = EIO;
        !           661:                else
        !           662:                        bp->b_flags |= B_ERROR;
        !           663:                splx(x);
        !           664:                return (bp->b_error);
        !           665:        } else {
        !           666:                splx(x);
        !           667:                return (0);
        !           668:        }
1.1       root      669: }
                    670: 
                    671: /*
1.1.1.2 ! root      672:  * Finish up operations on a buffer, calling an optional
        !           673:  * function (if requested), and releasing the buffer if
        !           674:  * marked asynchronous. Then mark this buffer done so that
        !           675:  * others biowait()'ing for it will notice when they are
        !           676:  * woken up from sleep().
1.1       root      677:  */
1.1.1.2 ! root      678: void
1.1       root      679: biodone(bp)
                    680:        register struct buf *bp;
                    681: {
1.1.1.2 ! root      682:        int x;
1.1       root      683: 
1.1.1.2 ! root      684:        x = splbio();
        !           685:        if (bp->b_flags & B_CALL) (*bp->b_iodone)(bp);
        !           686:        bp->b_flags &=  ~B_CALL;
        !           687:        if ((bp->b_flags & (B_READ|B_DIRTY)) == B_DIRTY)  {
        !           688:                bp->b_flags &=  ~B_DIRTY;
        !           689:                vwakeup(bp);
        !           690:        }
        !           691:        if (bp->b_flags & B_ASYNC)
        !           692:                brelse(bp);
        !           693:        bp->b_flags &=  ~B_ASYNC;
        !           694:        bp->b_flags |= B_DONE;
        !           695:        wakeup(bp);
        !           696:        splx(x);
1.1       root      697: }

unix.superglobalmegacorp.com

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