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

1.1       root        1: /*
                      2:  * Copyright (c) 1989, 1990, 1991, 1992 William F. Jolitz, TeleMuse
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This software is a component of "386BSD" developed by 
                     16:        William F. Jolitz, TeleMuse.
                     17:  * 4. Neither the name of the developer nor the name "386BSD"
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ 
                     22:  * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS 
                     23:  * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT. 
                     24:  * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT 
                     25:  * NOT MAKE USE THIS WORK.
                     26:  *
                     27:  * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
                     28:  * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN 
                     29:  * REFERENCES SUCH AS THE  "PORTING UNIX TO THE 386" SERIES 
                     30:  * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING 
                     31:  * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND 
                     32:  * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE 
                     33:  * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS 
                     34:  * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
                     35:  *
                     36:  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
                     37:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     38:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     39:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE DEVELOPER BE LIABLE
                     40:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     41:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     42:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     43:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     44:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     45:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     46:  * SUCH DAMAGE.
                     47:  *
1.1.1.3 ! root       48:  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
        !            49:  * --------------------         -----   ----------------------
        !            50:  * CURRENT PATCH LEVEL:         2       00042
        !            51:  * --------------------         -----   ----------------------
        !            52:  *
        !            53:  * 24 Apr 92   Martin Renters          Fix NFS read request hang
        !            54:  * 20 Aug 92   David Greenman          Fix getnewbuf() 2xAllocation
1.1       root       55:  */
1.1.1.3 ! root       56: static char rcsid[] = "$Header: /cvsroot/src/sys/kern/Attic/vfs__bio.c,v 1.2 1993/03/21 18:11:52 cgd Exp $";
1.1       root       57: 
                     58: #include "param.h"
                     59: #include "proc.h"
                     60: #include "vnode.h"
                     61: #include "buf.h"
                     62: #include "specdev.h"
                     63: #include "mount.h"
                     64: #include "malloc.h"
1.1.1.2   root       65: #include "vm/vm.h"
1.1       root       66: #include "resourcevar.h"
                     67: 
1.1.1.2   root       68: struct buf *getnewbuf(int);
                     69: extern vm_map_t buffer_map;
                     70: 
1.1       root       71: /*
                     72:  * Initialize buffer headers and related structures.
                     73:  */
                     74: void bufinit()
                     75: {
                     76:        struct bufhd *bh;
                     77:        struct buf *bp;
                     78: 
                     79:        /* first, make a null hash table */
                     80:        for(bh = bufhash; bh < bufhash + BUFHSZ; bh++) {
                     81:                bh->b_flags = 0;
                     82:                bh->b_forw = (struct buf *)bh;
                     83:                bh->b_back = (struct buf *)bh;
                     84:        }
                     85: 
                     86:        /* next, make a null set of free lists */
                     87:        for(bp = bfreelist; bp < bfreelist + BQUEUES; bp++) {
                     88:                bp->b_flags = 0;
                     89:                bp->av_forw = bp;
                     90:                bp->av_back = bp;
                     91:                bp->b_forw = bp;
                     92:                bp->b_back = bp;
                     93:        }
                     94: 
                     95:        /* finally, initialize each buffer header and stick on empty q */
                     96:        for(bp = buf; bp < buf + nbuf ; bp++) {
                     97:                bp->b_flags = B_HEAD | B_INVAL; /* we're just an empty header */
                     98:                bp->b_dev = NODEV;
                     99:                bp->b_vp = 0;
                    100:                binstailfree(bp, bfreelist + BQ_EMPTY);
                    101:                binshash(bp, bfreelist + BQ_EMPTY);
                    102:        }
                    103: }
                    104: 
                    105: /*
                    106:  * Find the block in the buffer pool.
                    107:  * If the buffer is not present, allocate a new buffer and load
                    108:  * its contents according to the filesystem fill routine.
                    109:  */
1.1.1.2   root      110: int
                    111: bread(struct vnode *vp, daddr_t blkno, int size, struct ucred *cred,
                    112:        struct buf **bpp)
1.1       root      113: {
                    114:        struct buf *bp;
                    115:        int rv = 0;
                    116: 
                    117:        bp = getblk (vp, blkno, size);
                    118: 
                    119:        /* if not found in cache, do some I/O */
                    120:        if ((bp->b_flags & B_CACHE) == 0 || (bp->b_flags & B_INVAL) != 0) {
                    121:                bp->b_flags |= B_READ;
                    122:                bp->b_flags &= ~(B_DONE|B_ERROR|B_INVAL);
1.1.1.3 ! root      123:                if (cred != NOCRED) crhold(cred);               /* 25 Apr 92*/
1.1.1.2   root      124:                bp->b_rcred = cred;
1.1       root      125:                VOP_STRATEGY(bp);
                    126:                rv = biowait (bp);
                    127:        }
                    128:        *bpp = bp;
                    129:        
                    130:        return (rv);
                    131: }
                    132: 
                    133: /*
                    134:  * Operates like bread, but also starts I/O on the specified
                    135:  * read-ahead block. [See page 55 of Bach's Book]
                    136:  */
1.1.1.2   root      137: int
                    138: breada(struct vnode *vp, daddr_t blkno, int size, daddr_t rablkno, int rabsize,
                    139:        struct ucred *cred, struct buf **bpp)
1.1       root      140: {
                    141:        struct buf *bp, *rabp;
                    142:        int rv = 0, needwait = 0;
                    143: 
                    144:        bp = getblk (vp, blkno, size);
                    145: 
                    146:        /* if not found in cache, do some I/O */
                    147:        if ((bp->b_flags & B_CACHE) == 0 || (bp->b_flags & B_INVAL) != 0) {
                    148:                bp->b_flags |= B_READ;
                    149:                bp->b_flags &= ~(B_DONE|B_ERROR|B_INVAL);
1.1.1.3 ! root      150:                if (cred != NOCRED) crhold(cred);               /* 25 Apr 92*/
1.1.1.2   root      151:                bp->b_rcred = cred;
1.1       root      152:                VOP_STRATEGY(bp);
                    153:                needwait++;
                    154:        }
                    155:        
                    156:        rabp = getblk (vp, rablkno, rabsize);
                    157: 
                    158:        /* if not found in cache, do some I/O (overlapped with first) */
                    159:        if ((rabp->b_flags & B_CACHE) == 0 || (rabp->b_flags & B_INVAL) != 0) {
                    160:                rabp->b_flags |= B_READ | B_ASYNC;
                    161:                rabp->b_flags &= ~(B_DONE|B_ERROR|B_INVAL);
1.1.1.3 ! root      162:                if (cred != NOCRED) crhold(cred);               /* 25 Apr 92*/
1.1.1.2   root      163:                rabp->b_rcred = cred;
1.1       root      164:                VOP_STRATEGY(rabp);
                    165:        } else
                    166:                brelse(rabp);
                    167:        
                    168:        /* wait for original I/O */
                    169:        if (needwait)
                    170:                rv = biowait (bp);
                    171: 
                    172:        *bpp = bp;
                    173:        return (rv);
                    174: }
                    175: 
                    176: /*
                    177:  * Synchronous write.
                    178:  * Release buffer on completion.
                    179:  */
1.1.1.2   root      180: int
                    181: bwrite(register struct buf *bp)
1.1       root      182: {
                    183:        int rv;
                    184: 
                    185:        if(bp->b_flags & B_INVAL) {
                    186:                brelse(bp);
                    187:                return (0);
                    188:        } else {
                    189:                int wasdelayed;
                    190: 
1.1.1.2   root      191:                if(!(bp->b_flags & B_BUSY))
                    192:                        panic("bwrite: not busy");
                    193: 
1.1       root      194:                wasdelayed = bp->b_flags & B_DELWRI;
                    195:                bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_ASYNC|B_DELWRI);
1.1.1.2   root      196:                if(wasdelayed)
                    197:                        reassignbuf(bp, bp->b_vp);
                    198: 
1.1       root      199:                bp->b_flags |= B_DIRTY;
1.1.1.2   root      200:                bp->b_vp->v_numoutput++;
1.1       root      201:                VOP_STRATEGY(bp);
                    202:                rv = biowait(bp);
                    203:                brelse(bp);
                    204:                return (rv);
                    205:        }
                    206: }
                    207: 
                    208: /*
                    209:  * Delayed write.
                    210:  *
                    211:  * The buffer is marked dirty, but is not queued for I/O.
                    212:  * This routine should be used when the buffer is expected
                    213:  * to be modified again soon, typically a small write that
                    214:  * partially fills a buffer.
                    215:  *
                    216:  * NB: magnetic tapes cannot be delayed; they must be
                    217:  * written in the order that the writes are requested.
                    218:  */
1.1.1.2   root      219: void
                    220: bdwrite(register struct buf *bp)
1.1       root      221: {
                    222: 
1.1.1.2   root      223:        if(!(bp->b_flags & B_BUSY))
                    224:                panic("bdwrite: not busy");
                    225: 
1.1       root      226:        if(bp->b_flags & B_INVAL) {
                    227:                brelse(bp);
                    228:        }
                    229:        if(bp->b_flags & B_TAPE) {
                    230:                bwrite(bp);
                    231:                return;
                    232:        }
                    233:        bp->b_flags &= ~(B_READ|B_DONE);
                    234:        bp->b_flags |= B_DIRTY|B_DELWRI;
                    235:        reassignbuf(bp, bp->b_vp);
                    236:        brelse(bp);
                    237:        return;
                    238: }
                    239: 
                    240: /*
                    241:  * Asynchronous write.
                    242:  * Start I/O on a buffer, but do not wait for it to complete.
                    243:  * The buffer is released when the I/O completes.
                    244:  */
1.1.1.2   root      245: void
                    246: bawrite(register struct buf *bp)
1.1       root      247: {
                    248: 
1.1.1.2   root      249:        if(!(bp->b_flags & B_BUSY))
                    250:                panic("bawrite: not busy");
                    251: 
1.1       root      252:        if(bp->b_flags & B_INVAL)
                    253:                brelse(bp);
                    254:        else {
                    255:                int wasdelayed;
                    256: 
                    257:                wasdelayed = bp->b_flags & B_DELWRI;
                    258:                bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
1.1.1.2   root      259:                if(wasdelayed)
                    260:                        reassignbuf(bp, bp->b_vp);
1.1       root      261: 
                    262:                bp->b_flags |= B_DIRTY | B_ASYNC;
1.1.1.2   root      263:                bp->b_vp->v_numoutput++;
1.1       root      264:                VOP_STRATEGY(bp);
                    265:        }
                    266: }
                    267: 
                    268: /*
                    269:  * Release a buffer.
                    270:  * Even if the buffer is dirty, no I/O is started.
                    271:  */
1.1.1.2   root      272: void
                    273: brelse(register struct buf *bp)
1.1       root      274: {
                    275:        int x;
                    276: 
                    277:        /* anyone need a "free" block? */
                    278:        x=splbio();
                    279:        if ((bfreelist + BQ_AGE)->b_flags & B_WANTED) {
                    280:                (bfreelist + BQ_AGE) ->b_flags &= ~B_WANTED;
                    281:                wakeup(bfreelist);
                    282:        }
                    283:        /* anyone need this very block? */
                    284:        if (bp->b_flags & B_WANTED) {
                    285:                bp->b_flags &= ~B_WANTED;
                    286:                wakeup(bp);
                    287:        }
                    288: 
                    289:        if (bp->b_flags & (B_INVAL|B_ERROR)) {
                    290:                bp->b_flags |= B_INVAL;
                    291:                bp->b_flags &= ~(B_DELWRI|B_CACHE);
                    292:                if(bp->b_vp)
                    293:                        brelvp(bp);
                    294:        }
                    295: 
                    296:        /* enqueue */
                    297:        /* just an empty buffer head ... */
                    298:        /*if(bp->b_flags & B_HEAD)
                    299:                binsheadfree(bp, bfreelist + BQ_EMPTY)*/
                    300:        /* buffers with junk contents */
                    301:        /*else*/ if(bp->b_flags & (B_ERROR|B_INVAL|B_NOCACHE))
                    302:                binsheadfree(bp, bfreelist + BQ_AGE)
                    303:        /* buffers with stale but valid contents */
                    304:        else if(bp->b_flags & B_AGE)
                    305:                binstailfree(bp, bfreelist + BQ_AGE)
                    306:        /* buffers with valid and quite potentially reuseable contents */
                    307:        else
                    308:                binstailfree(bp, bfreelist + BQ_LRU)
                    309: 
                    310:        /* unlock */
                    311:        bp->b_flags &= ~B_BUSY;
                    312:        splx(x);
                    313: 
                    314: }
                    315: 
1.1.1.2   root      316: int freebufspace;
1.1       root      317: int allocbufspace;
                    318: 
                    319: /*
                    320:  * Find a buffer which is available for use.
                    321:  * If free memory for buffer space and an empty header from the empty list,
                    322:  * use that. Otherwise, select something from a free list.
                    323:  * Preference is to AGE list, then LRU list.
                    324:  */
1.1.1.2   root      325: static struct buf *
                    326: getnewbuf(int sz)
1.1       root      327: {
                    328:        struct buf *bp;
                    329:        int x;
                    330: 
                    331:        x = splbio();
                    332: start:
                    333:        /* can we constitute a new buffer? */
                    334:        if (freebufspace > sz
                    335:                && bfreelist[BQ_EMPTY].av_forw != (struct buf *)bfreelist+BQ_EMPTY) {
                    336:                caddr_t addr;
                    337: 
1.1.1.2   root      338: /*#define notyet*/
                    339: #ifndef notyet
                    340:                if ((addr = malloc (sz, M_TEMP, M_WAITOK)) == 0) goto tryfree;
                    341: #else /* notyet */
                    342:                /* get new memory buffer */
                    343:                if (round_page(sz) == sz)
                    344:                        addr = (caddr_t) kmem_alloc_wired_wait(buffer_map, sz);
                    345:                else
                    346:                        addr = (caddr_t) malloc (sz, M_TEMP, M_WAITOK);
                    347:        /*if ((addr = malloc (sz, M_TEMP, M_NOWAIT)) == 0) goto tryfree;*/
                    348:                bzero(addr, sz);
                    349: #endif /* notyet */
1.1       root      350:                freebufspace -= sz;
                    351:                allocbufspace += sz;
                    352: 
                    353:                bp = bfreelist[BQ_EMPTY].av_forw;
                    354:                bp->b_flags = B_BUSY | B_INVAL;
                    355:                bremfree(bp);
1.1.1.2   root      356:                bp->b_un.b_addr = addr;
1.1.1.3 ! root      357:                bp->b_bufsize = sz;     /* 20 Aug 92*/
1.1       root      358:                goto fillin;
                    359:        }
                    360: 
                    361: tryfree:
                    362:        if (bfreelist[BQ_AGE].av_forw != (struct buf *)bfreelist+BQ_AGE) {
                    363:                bp = bfreelist[BQ_AGE].av_forw;
                    364:                bremfree(bp);
                    365:        } else if (bfreelist[BQ_LRU].av_forw != (struct buf *)bfreelist+BQ_LRU) {
                    366:                bp = bfreelist[BQ_LRU].av_forw;
                    367:                bremfree(bp);
                    368:        } else  {
                    369:                /* wait for a free buffer of any kind */
                    370:                (bfreelist + BQ_AGE)->b_flags |= B_WANTED;
                    371:                sleep(bfreelist, PRIBIO);
                    372:                splx(x);
                    373:                return (0);
                    374:        }
                    375: 
                    376:        /* if we are a delayed write, convert to an async write! */
                    377:        if (bp->b_flags & B_DELWRI) {
                    378:                bp->b_flags |= B_BUSY;
                    379:                bawrite (bp);
                    380:                goto start;
                    381:        }
                    382: 
                    383: 
                    384:        if(bp->b_vp)
                    385:                brelvp(bp);
                    386: 
                    387:        /* we are not free, nor do we contain interesting data */
1.1.1.3 ! root      388:        if (bp->b_rcred != NOCRED) crfree(bp->b_rcred);         /* 25 Apr 92*/
        !           389:        if (bp->b_wcred != NOCRED) crfree(bp->b_wcred);
1.1       root      390:        bp->b_flags = B_BUSY;
                    391: fillin:
                    392:        bremhash(bp);
                    393:        splx(x);
                    394:        bp->b_dev = NODEV;
                    395:        bp->b_vp = NULL;
                    396:        bp->b_blkno = bp->b_lblkno = 0;
                    397:        bp->b_iodone = 0;
                    398:        bp->b_error = 0;
                    399:        bp->b_wcred = bp->b_rcred = NOCRED;
1.1.1.2   root      400:        if (bp->b_bufsize != sz)
                    401:                allocbuf(bp, sz);
1.1       root      402:        bp->b_bcount = bp->b_bufsize = sz;
                    403:        bp->b_dirtyoff = bp->b_dirtyend = 0;
                    404:        return (bp);
                    405: }
                    406: 
                    407: /*
                    408:  * Check to see if a block is currently memory resident.
                    409:  */
1.1.1.2   root      410: struct buf *
                    411: incore(struct vnode *vp, daddr_t blkno)
1.1       root      412: {
                    413:        struct buf *bh;
                    414:        struct buf *bp;
                    415: 
                    416:        bh = BUFHASH(vp, blkno);
                    417: 
                    418:        /* Search hash chain */
                    419:        bp = bh->b_forw;
                    420:        while (bp != (struct buf *) bh) {
                    421:                /* hit */
                    422:                if (bp->b_lblkno == blkno && bp->b_vp == vp
                    423:                        && (bp->b_flags & B_INVAL) == 0)
                    424:                        return (bp);
                    425:                bp = bp->b_forw;
                    426:        }
                    427:        
                    428:        return(0);
                    429: }
                    430: 
                    431: /*
                    432:  * Get a block of requested size that is associated with
                    433:  * a given vnode and block offset. If it is found in the
                    434:  * block cache, mark it as having been found, make it busy
                    435:  * and return it. Otherwise, return an empty block of the
                    436:  * correct size. It is up to the caller to insure that the
                    437:  * cached blocks be of the correct size.
                    438:  */
                    439: struct buf *
1.1.1.2   root      440: getblk(register struct vnode *vp, daddr_t blkno, int size)
1.1       root      441: {
                    442:        struct buf *bp, *bh;
                    443:        int x;
                    444: 
                    445:        for (;;) {
                    446:                if (bp = incore(vp, blkno)) {
                    447:                        x = splbio();
                    448:                        if (bp->b_flags & B_BUSY) {
                    449:                                bp->b_flags |= B_WANTED;
                    450:                                sleep (bp, PRIBIO);
1.1.1.2   root      451:                                splx(x);
1.1       root      452:                                continue;
                    453:                        }
                    454:                        bp->b_flags |= B_BUSY | B_CACHE;
                    455:                        bremfree(bp);
                    456:                        if (size > bp->b_bufsize)
                    457:                                panic("now what do we do?");
                    458:                        /* if (bp->b_bufsize != size) allocbuf(bp, size); */
                    459:                } else {
                    460: 
                    461:                        if((bp = getnewbuf(size)) == 0) continue;
                    462:                        bp->b_blkno = bp->b_lblkno = blkno;
                    463:                        bgetvp(vp, bp);
                    464:                        x = splbio();
                    465:                        bh = BUFHASH(vp, blkno);
                    466:                        binshash(bp, bh);
                    467:                        bp->b_flags = B_BUSY;
                    468:                }
                    469:                splx(x);
                    470:                return (bp);
                    471:        }
                    472: }
                    473: 
                    474: /*
                    475:  * Get an empty, disassociated buffer of given size.
                    476:  */
                    477: struct buf *
1.1.1.2   root      478: geteblk(int size)
1.1       root      479: {
                    480:        struct buf *bp;
                    481:        int x;
                    482: 
                    483:        while ((bp = getnewbuf(size)) == 0)
                    484:                ;
                    485:        x = splbio();
                    486:        binshash(bp, bfreelist + BQ_AGE);
                    487:        splx(x);
                    488: 
                    489:        return (bp);
                    490: }
                    491: 
                    492: /*
                    493:  * Exchange a buffer's underlying buffer storage for one of different
                    494:  * size, taking care to maintain contents appropriately. When buffer
                    495:  * increases in size, caller is responsible for filling out additional
                    496:  * contents. When buffer shrinks in size, data is lost, so caller must
                    497:  * first return it to backing store before shrinking the buffer, as
                    498:  * no implied I/O will be done.
                    499:  *
                    500:  * Expanded buffer is returned as value.
                    501:  */
1.1.1.2   root      502: void
                    503: allocbuf(register struct buf *bp, int size)
1.1       root      504: {
                    505:        caddr_t newcontents;
                    506: 
                    507:        /* get new memory buffer */
1.1.1.2   root      508: #ifndef notyet
1.1       root      509:        newcontents = (caddr_t) malloc (size, M_TEMP, M_WAITOK);
1.1.1.2   root      510: #else /* notyet */
                    511:        if (round_page(size) == size)
                    512:                newcontents = (caddr_t) kmem_alloc_wired_wait(buffer_map, size);
                    513:        else
                    514:                newcontents = (caddr_t) malloc (size, M_TEMP, M_WAITOK);
                    515: #endif /* notyet */
1.1       root      516: 
                    517:        /* copy the old into the new, up to the maximum that will fit */
                    518:        bcopy (bp->b_un.b_addr, newcontents, min(bp->b_bufsize, size));
                    519: 
                    520:        /* return old contents to free heap */
1.1.1.2   root      521: #ifndef notyet
1.1       root      522:        free (bp->b_un.b_addr, M_TEMP);
1.1.1.2   root      523: #else /* notyet */
                    524:        if (round_page(bp->b_bufsize) == bp->b_bufsize)
                    525:                kmem_free_wakeup(buffer_map, bp->b_un.b_addr, bp->b_bufsize);
                    526:        else
                    527:                free (bp->b_un.b_addr, M_TEMP);
                    528: #endif /* notyet */
1.1       root      529: 
                    530:        /* adjust buffer cache's idea of memory allocated to buffer contents */
                    531:        freebufspace -= size - bp->b_bufsize;
                    532:        allocbufspace += size - bp->b_bufsize;
                    533: 
                    534:        /* update buffer header */
                    535:        bp->b_un.b_addr = newcontents;
                    536:        bp->b_bcount = bp->b_bufsize = size;
                    537: }
                    538: 
                    539: /*
                    540:  * Patiently await operations to complete on this buffer.
                    541:  * When they do, extract error value and return it.
                    542:  * Extract and return any errors associated with the I/O.
                    543:  * If an invalid block, force it off the lookup hash chains.
                    544:  */
1.1.1.2   root      545: int
                    546: biowait(register struct buf *bp)
1.1       root      547: {
                    548:        int x;
                    549: 
                    550:        x = splbio();
                    551:        while ((bp->b_flags & B_DONE) == 0)
                    552:                sleep((caddr_t)bp, PRIBIO);
                    553:        if((bp->b_flags & B_ERROR) || bp->b_error) {
                    554:                if ((bp->b_flags & B_INVAL) == 0) {
                    555:                        bp->b_flags |= B_INVAL;
                    556:                        bremhash(bp);
                    557:                        binshash(bp, bfreelist + BQ_AGE);
                    558:                }
                    559:                if (!bp->b_error)
                    560:                        bp->b_error = EIO;
                    561:                else
                    562:                        bp->b_flags |= B_ERROR;
                    563:                splx(x);
                    564:                return (bp->b_error);
                    565:        } else {
                    566:                splx(x);
                    567:                return (0);
                    568:        }
                    569: }
                    570: 
                    571: /*
                    572:  * Finish up operations on a buffer, calling an optional
                    573:  * function (if requested), and releasing the buffer if
                    574:  * marked asynchronous. Then mark this buffer done so that
                    575:  * others biowait()'ing for it will notice when they are
                    576:  * woken up from sleep().
                    577:  */
1.1.1.2   root      578: int
                    579: biodone(register struct buf *bp)
1.1       root      580: {
                    581:        int x;
                    582: 
                    583:        x = splbio();
                    584:        if (bp->b_flags & B_CALL) (*bp->b_iodone)(bp);
                    585:        bp->b_flags &=  ~B_CALL;
1.1.1.2   root      586:        if ((bp->b_flags & (B_READ|B_DIRTY)) == B_DIRTY)  {
                    587:                bp->b_flags &=  ~B_DIRTY;
                    588:                vwakeup(bp);
                    589:        }
                    590:        if (bp->b_flags & B_ASYNC)
                    591:                brelse(bp);
1.1       root      592:        bp->b_flags &=  ~B_ASYNC;
                    593:        bp->b_flags |= B_DONE;
                    594:        wakeup(bp);
                    595:        splx(x);
                    596: }

unix.superglobalmegacorp.com

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