149589Sbostic /*- 249589Sbostic * Copyright (c) 1982, 1986, 1989 The Regents of the University of California. 337736Smckusick * All rights reserved. 423395Smckusick * 549618Smckusick * This module is believed to contain source code proprietary to AT&T. 649618Smckusick * Use and redistribution is subject to the Berkeley Software License 749618Smckusick * Agreement and your Software Agreement with AT&T (Western Electric). 837736Smckusick * 9*52189Smckusick * @(#)vfs_cluster.c 7.45 (Berkeley) 01/14/92 1023395Smckusick */ 118Sbill 1251455Sbostic #include <sys/param.h> 1351455Sbostic #include <sys/proc.h> 1451455Sbostic #include <sys/buf.h> 1551455Sbostic #include <sys/vnode.h> 1651455Sbostic #include <sys/specdev.h> 1751455Sbostic #include <sys/mount.h> 1851455Sbostic #include <sys/trace.h> 1951455Sbostic #include <sys/resourcevar.h> 208Sbill 2191Sbill /* 2249280Skarels * Initialize buffers and hash links for buffers. 2349280Skarels */ 2451455Sbostic void 2549280Skarels bufinit() 2649280Skarels { 2749280Skarels register int i; 2849280Skarels register struct buf *bp, *dp; 2949280Skarels register struct bufhd *hp; 3049280Skarels int base, residual; 3149280Skarels 3249280Skarels for (hp = bufhash, i = 0; i < BUFHSZ; i++, hp++) 3349280Skarels hp->b_forw = hp->b_back = (struct buf *)hp; 3449280Skarels 3549280Skarels for (dp = bfreelist; dp < &bfreelist[BQUEUES]; dp++) { 3649280Skarels dp->b_forw = dp->b_back = dp->av_forw = dp->av_back = dp; 3749280Skarels dp->b_flags = B_HEAD; 3849280Skarels } 3949280Skarels base = bufpages / nbuf; 4049280Skarels residual = bufpages % nbuf; 4149280Skarels for (i = 0; i < nbuf; i++) { 4249280Skarels bp = &buf[i]; 4349280Skarels bp->b_dev = NODEV; 4449280Skarels bp->b_bcount = 0; 4549280Skarels bp->b_rcred = NOCRED; 4649280Skarels bp->b_wcred = NOCRED; 4749280Skarels bp->b_dirtyoff = 0; 4849280Skarels bp->b_dirtyend = 0; 49*52189Smckusick bp->b_validoff = 0; 50*52189Smckusick bp->b_validend = 0; 5149280Skarels bp->b_un.b_addr = buffers + i * MAXBSIZE; 5249280Skarels if (i < residual) 5349280Skarels bp->b_bufsize = (base + 1) * CLBYTES; 5449280Skarels else 5549280Skarels bp->b_bufsize = base * CLBYTES; 5649280Skarels binshash(bp, &bfreelist[BQ_AGE]); 5749280Skarels bp->b_flags = B_BUSY|B_INVAL; 5849280Skarels brelse(bp); 5949280Skarels } 6049280Skarels } 6149280Skarels 6249280Skarels /* 6346151Smckusick * Find the block in the buffer pool. 6446151Smckusick * If the buffer is not present, allocate a new buffer and load 6546151Smckusick * its contents according to the filesystem fill routine. 668Sbill */ 6738776Smckusick bread(vp, blkno, size, cred, bpp) 6837736Smckusick struct vnode *vp; 696563Smckusic daddr_t blkno; 706563Smckusic int size; 7138776Smckusick struct ucred *cred; 7237736Smckusick struct buf **bpp; 738Sbill { 7447545Skarels struct proc *p = curproc; /* XXX */ 758Sbill register struct buf *bp; 768Sbill 778670S if (size == 0) 788670S panic("bread: size 0"); 7937736Smckusick *bpp = bp = getblk(vp, blkno, size); 8046151Smckusick if (bp->b_flags & (B_DONE | B_DELWRI)) { 8140341Smckusick trace(TR_BREADHIT, pack(vp, size), blkno); 8237736Smckusick return (0); 838Sbill } 848Sbill bp->b_flags |= B_READ; 858670S if (bp->b_bcount > bp->b_bufsize) 868670S panic("bread"); 8738776Smckusick if (bp->b_rcred == NOCRED && cred != NOCRED) { 8838776Smckusick crhold(cred); 8938776Smckusick bp->b_rcred = cred; 9038776Smckusick } 9137736Smckusick VOP_STRATEGY(bp); 9240341Smckusick trace(TR_BREADMISS, pack(vp, size), blkno); 9347545Skarels p->p_stats->p_ru.ru_inblock++; /* pay for read */ 9437736Smckusick return (biowait(bp)); 958Sbill } 968Sbill 978Sbill /* 98*52189Smckusick * Operates like bread, but also starts I/O on the N specified 99*52189Smckusick * read-ahead blocks. 1008Sbill */ 101*52189Smckusick breadn(vp, blkno, size, rablkno, rabsize, num, cred, bpp) 10237736Smckusick struct vnode *vp; 1037114Smckusick daddr_t blkno; int size; 104*52189Smckusick daddr_t rablkno[]; int rabsize[]; 105*52189Smckusick int num; 10638776Smckusick struct ucred *cred; 10737736Smckusick struct buf **bpp; 1088Sbill { 10947545Skarels struct proc *p = curproc; /* XXX */ 1108Sbill register struct buf *bp, *rabp; 111*52189Smckusick register int i; 1128Sbill 1138Sbill bp = NULL; 1147015Smckusick /* 11546151Smckusick * If the block is not memory resident, 11646151Smckusick * allocate a buffer and start I/O. 1177015Smckusick */ 11837736Smckusick if (!incore(vp, blkno)) { 11937736Smckusick *bpp = bp = getblk(vp, blkno, size); 12046151Smckusick if ((bp->b_flags & (B_DONE | B_DELWRI)) == 0) { 1218Sbill bp->b_flags |= B_READ; 1228670S if (bp->b_bcount > bp->b_bufsize) 123*52189Smckusick panic("breadn"); 12438776Smckusick if (bp->b_rcred == NOCRED && cred != NOCRED) { 12538776Smckusick crhold(cred); 12638776Smckusick bp->b_rcred = cred; 12738776Smckusick } 12837736Smckusick VOP_STRATEGY(bp); 12940341Smckusick trace(TR_BREADMISS, pack(vp, size), blkno); 13047545Skarels p->p_stats->p_ru.ru_inblock++; /* pay for read */ 1317015Smckusick } else 13240341Smckusick trace(TR_BREADHIT, pack(vp, size), blkno); 1338Sbill } 1347015Smckusick 1357015Smckusick /* 136*52189Smckusick * If there's read-ahead block(s), start I/O 137*52189Smckusick * on them also (as above). 1387015Smckusick */ 139*52189Smckusick for (i = 0; i < num; i++) { 140*52189Smckusick if (incore(vp, rablkno[i])) 141*52189Smckusick continue; 142*52189Smckusick rabp = getblk(vp, rablkno[i], rabsize[i]); 14346151Smckusick if (rabp->b_flags & (B_DONE | B_DELWRI)) { 1448Sbill brelse(rabp); 145*52189Smckusick trace(TR_BREADHITRA, pack(vp, rabsize[i]), rablkno[i]); 1462045Swnj } else { 14746151Smckusick rabp->b_flags |= B_ASYNC | B_READ; 1488670S if (rabp->b_bcount > rabp->b_bufsize) 1498670S panic("breadrabp"); 15038880Smckusick if (rabp->b_rcred == NOCRED && cred != NOCRED) { 15138776Smckusick crhold(cred); 15238880Smckusick rabp->b_rcred = cred; 15338776Smckusick } 15437736Smckusick VOP_STRATEGY(rabp); 155*52189Smckusick trace(TR_BREADMISSRA, pack(vp, rabsize[i]), rablkno[i]); 15647545Skarels p->p_stats->p_ru.ru_inblock++; /* pay in advance */ 1578Sbill } 1588Sbill } 1597015Smckusick 1607015Smckusick /* 16146151Smckusick * If block was memory resident, let bread get it. 16246151Smckusick * If block was not memory resident, the read was 16346151Smckusick * started above, so just wait for the read to complete. 1647015Smckusick */ 1657114Smckusick if (bp == NULL) 16638776Smckusick return (bread(vp, blkno, size, cred, bpp)); 16737736Smckusick return (biowait(bp)); 1688Sbill } 1698Sbill 1708Sbill /* 17146151Smckusick * Synchronous write. 17246151Smckusick * Release buffer on completion. 1738Sbill */ 1748Sbill bwrite(bp) 1757015Smckusick register struct buf *bp; 1768Sbill { 17747545Skarels struct proc *p = curproc; /* XXX */ 17837736Smckusick register int flag; 17940226Smckusick int s, error; 1808Sbill 1818Sbill flag = bp->b_flags; 1829857Ssam bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI); 18349459Smckusick if (flag & B_ASYNC) { 18449459Smckusick if ((flag & B_DELWRI) == 0) 18549459Smckusick p->p_stats->p_ru.ru_oublock++; /* no one paid yet */ 18649459Smckusick else 18749459Smckusick reassignbuf(bp, bp->b_vp); 18849459Smckusick } 18940341Smckusick trace(TR_BWRITE, pack(bp->b_vp, bp->b_bcount), bp->b_lblkno); 1908670S if (bp->b_bcount > bp->b_bufsize) 1918670S panic("bwrite"); 19240226Smckusick s = splbio(); 19339882Smckusick bp->b_vp->v_numoutput++; 19440226Smckusick splx(s); 19537736Smckusick VOP_STRATEGY(bp); 1967015Smckusick 1977015Smckusick /* 19846151Smckusick * If the write was synchronous, then await I/O completion. 1997015Smckusick * If the write was "delayed", then we put the buffer on 20046151Smckusick * the queue of blocks awaiting I/O completion status. 2017015Smckusick */ 20246151Smckusick if ((flag & B_ASYNC) == 0) { 20337736Smckusick error = biowait(bp); 20449459Smckusick if ((flag&B_DELWRI) == 0) 20549459Smckusick p->p_stats->p_ru.ru_oublock++; /* no one paid yet */ 20649459Smckusick else 20749459Smckusick reassignbuf(bp, bp->b_vp); 2088Sbill brelse(bp); 20937736Smckusick } else if (flag & B_DELWRI) { 2108Sbill bp->b_flags |= B_AGE; 21137736Smckusick error = 0; 21237736Smckusick } 21337736Smckusick return (error); 2148Sbill } 2158Sbill 2168Sbill /* 21746151Smckusick * Delayed write. 21846151Smckusick * 21946151Smckusick * The buffer is marked dirty, but is not queued for I/O. 22046151Smckusick * This routine should be used when the buffer is expected 22146151Smckusick * to be modified again soon, typically a small write that 22246151Smckusick * partially fills a buffer. 22346151Smckusick * 22446151Smckusick * NB: magnetic tapes cannot be delayed; they must be 22546151Smckusick * written in the order that the writes are requested. 2268Sbill */ 2278Sbill bdwrite(bp) 2287015Smckusick register struct buf *bp; 2298Sbill { 23047545Skarels struct proc *p = curproc; /* XXX */ 2318Sbill 23239882Smckusick if ((bp->b_flags & B_DELWRI) == 0) { 23339882Smckusick bp->b_flags |= B_DELWRI; 23439882Smckusick reassignbuf(bp, bp->b_vp); 23547545Skarels p->p_stats->p_ru.ru_oublock++; /* no one paid yet */ 23639882Smckusick } 23737736Smckusick /* 23839668Smckusick * If this is a tape drive, the write must be initiated. 23937736Smckusick */ 24048360Smckusick if (VOP_IOCTL(bp->b_vp, 0, (caddr_t)B_TAPE, 0, NOCRED, p) == 0) { 2418Sbill bawrite(bp); 24239668Smckusick } else { 24346151Smckusick bp->b_flags |= (B_DONE | B_DELWRI); 2448Sbill brelse(bp); 2458Sbill } 2468Sbill } 2478Sbill 2488Sbill /* 24946151Smckusick * Asynchronous write. 25046151Smckusick * Start I/O on a buffer, but do not wait for it to complete. 25146151Smckusick * The buffer is released when the I/O completes. 2528Sbill */ 2538Sbill bawrite(bp) 2547015Smckusick register struct buf *bp; 2558Sbill { 2568Sbill 25746151Smckusick /* 25846151Smckusick * Setting the ASYNC flag causes bwrite to return 25946151Smckusick * after starting the I/O. 26046151Smckusick */ 2618Sbill bp->b_flags |= B_ASYNC; 26237736Smckusick (void) bwrite(bp); 2638Sbill } 2648Sbill 2658Sbill /* 26646151Smckusick * Release a buffer. 26746151Smckusick * Even if the buffer is dirty, no I/O is started. 2688Sbill */ 2698Sbill brelse(bp) 2707015Smckusick register struct buf *bp; 2718Sbill { 2722325Swnj register struct buf *flist; 27346151Smckusick int s; 2748Sbill 27540341Smckusick trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno); 2767015Smckusick /* 27739668Smckusick * If a process is waiting for the buffer, or 27839668Smckusick * is waiting for a free buffer, awaken it. 2797015Smckusick */ 28046151Smckusick if (bp->b_flags & B_WANTED) 2818Sbill wakeup((caddr_t)bp); 28246151Smckusick if (bfreelist[0].b_flags & B_WANTED) { 2832325Swnj bfreelist[0].b_flags &= ~B_WANTED; 2842325Swnj wakeup((caddr_t)bfreelist); 2858Sbill } 28639668Smckusick /* 28739668Smckusick * Retry I/O for locked buffers rather than invalidating them. 28839668Smckusick */ 28939668Smckusick if ((bp->b_flags & B_ERROR) && (bp->b_flags & B_LOCKED)) 29039668Smckusick bp->b_flags &= ~B_ERROR; 29139668Smckusick /* 29239668Smckusick * Disassociate buffers that are no longer valid. 29339668Smckusick */ 29446151Smckusick if (bp->b_flags & (B_NOCACHE | B_ERROR)) 29537736Smckusick bp->b_flags |= B_INVAL; 29646151Smckusick if ((bp->b_bufsize <= 0) || (bp->b_flags & (B_ERROR | B_INVAL))) { 29739668Smckusick if (bp->b_vp) 29839668Smckusick brelvp(bp); 29939668Smckusick bp->b_flags &= ~B_DELWRI; 30037736Smckusick } 3017015Smckusick /* 3027015Smckusick * Stick the buffer back on a free list. 3037015Smckusick */ 30426271Skarels s = splbio(); 3058670S if (bp->b_bufsize <= 0) { 3068670S /* block has no buffer ... put at front of unused buffer list */ 3078670S flist = &bfreelist[BQ_EMPTY]; 3088670S binsheadfree(bp, flist); 30946151Smckusick } else if (bp->b_flags & (B_ERROR | B_INVAL)) { 3102325Swnj /* block has no info ... put at front of most free list */ 3118670S flist = &bfreelist[BQ_AGE]; 3127015Smckusick binsheadfree(bp, flist); 3138Sbill } else { 3142325Swnj if (bp->b_flags & B_LOCKED) 3152325Swnj flist = &bfreelist[BQ_LOCKED]; 3162325Swnj else if (bp->b_flags & B_AGE) 3172325Swnj flist = &bfreelist[BQ_AGE]; 3182325Swnj else 3192325Swnj flist = &bfreelist[BQ_LRU]; 3207015Smckusick binstailfree(bp, flist); 3218Sbill } 32246151Smckusick bp->b_flags &= ~(B_WANTED | B_BUSY | B_ASYNC | B_AGE | B_NOCACHE); 3238Sbill splx(s); 3248Sbill } 3258Sbill 3268Sbill /* 32746151Smckusick * Check to see if a block is currently memory resident. 3288Sbill */ 32937736Smckusick incore(vp, blkno) 33037736Smckusick struct vnode *vp; 3317015Smckusick daddr_t blkno; 3328Sbill { 3338Sbill register struct buf *bp; 3342325Swnj register struct buf *dp; 3358Sbill 33638225Smckusick dp = BUFHASH(vp, blkno); 3372325Swnj for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) 33839668Smckusick if (bp->b_lblkno == blkno && bp->b_vp == vp && 3397015Smckusick (bp->b_flags & B_INVAL) == 0) 34091Sbill return (1); 34191Sbill return (0); 3428Sbill } 3438Sbill 34439668Smckusick /* 34546151Smckusick * Check to see if a block is currently memory resident. 34646151Smckusick * If it is resident, return it. If it is not resident, 34746151Smckusick * allocate a new buffer and assign it to the block. 34839668Smckusick */ 3498Sbill struct buf * 35037736Smckusick getblk(vp, blkno, size) 35137736Smckusick register struct vnode *vp; 3526563Smckusic daddr_t blkno; 3536563Smckusic int size; 3548Sbill { 3558670S register struct buf *bp, *dp; 3565424Swnj int s; 3578Sbill 35825255Smckusick if (size > MAXBSIZE) 35925255Smckusick panic("getblk: size too big"); 3607015Smckusick /* 36146151Smckusick * Search the cache for the block. If the buffer is found, 36246151Smckusick * but it is currently locked, the we must wait for it to 36346151Smckusick * become available. 3647015Smckusick */ 36537736Smckusick dp = BUFHASH(vp, blkno); 3667015Smckusick loop: 3672325Swnj for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) { 36839668Smckusick if (bp->b_lblkno != blkno || bp->b_vp != vp || 36946151Smckusick (bp->b_flags & B_INVAL)) 3708Sbill continue; 37126271Skarels s = splbio(); 37246151Smckusick if (bp->b_flags & B_BUSY) { 3738Sbill bp->b_flags |= B_WANTED; 37446151Smckusick sleep((caddr_t)bp, PRIBIO + 1); 3755424Swnj splx(s); 3768Sbill goto loop; 3778Sbill } 37839882Smckusick bremfree(bp); 37939882Smckusick bp->b_flags |= B_BUSY; 3805424Swnj splx(s); 38132608Smckusick if (bp->b_bcount != size) { 38239668Smckusick printf("getblk: stray size"); 38339668Smckusick bp->b_flags |= B_INVAL; 38439668Smckusick bwrite(bp); 38539668Smckusick goto loop; 38632608Smckusick } 3878Sbill bp->b_flags |= B_CACHE; 38826271Skarels return (bp); 3898Sbill } 3908670S bp = getnewbuf(); 3917015Smckusick bremhash(bp); 39239668Smckusick bgetvp(vp, bp); 39345116Smckusick bp->b_bcount = 0; 39439668Smckusick bp->b_lblkno = blkno; 3956563Smckusic bp->b_blkno = blkno; 3968670S bp->b_error = 0; 39737736Smckusick bp->b_resid = 0; 39837736Smckusick binshash(bp, dp); 39945116Smckusick allocbuf(bp, size); 40026271Skarels return (bp); 4018Sbill } 4028Sbill 4038Sbill /* 40446151Smckusick * Allocate a buffer. 40546151Smckusick * The caller will assign it to a block. 4068Sbill */ 4078Sbill struct buf * 4086563Smckusic geteblk(size) 4096563Smckusic int size; 4108Sbill { 4118670S register struct buf *bp, *flist; 4128Sbill 41325255Smckusick if (size > MAXBSIZE) 41425255Smckusick panic("geteblk: size too big"); 4158670S bp = getnewbuf(); 4168670S bp->b_flags |= B_INVAL; 4177015Smckusick bremhash(bp); 4188670S flist = &bfreelist[BQ_AGE]; 41945116Smckusick bp->b_bcount = 0; 42037736Smckusick bp->b_error = 0; 42137736Smckusick bp->b_resid = 0; 4228670S binshash(bp, flist); 42345116Smckusick allocbuf(bp, size); 42426271Skarels return (bp); 4258Sbill } 4268Sbill 4278Sbill /* 42845116Smckusick * Expand or contract the actual memory allocated to a buffer. 42946151Smckusick * If no memory is available, release buffer and take error exit. 4306563Smckusic */ 43145116Smckusick allocbuf(tp, size) 43245116Smckusick register struct buf *tp; 4336563Smckusic int size; 4346563Smckusic { 43545116Smckusick register struct buf *bp, *ep; 43645116Smckusick int sizealloc, take, s; 4376563Smckusic 43845116Smckusick sizealloc = roundup(size, CLBYTES); 43945116Smckusick /* 44045116Smckusick * Buffer size does not change 44145116Smckusick */ 44245116Smckusick if (sizealloc == tp->b_bufsize) 44345116Smckusick goto out; 44445116Smckusick /* 44545116Smckusick * Buffer size is shrinking. 44645116Smckusick * Place excess space in a buffer header taken from the 44745116Smckusick * BQ_EMPTY buffer list and placed on the "most free" list. 44845116Smckusick * If no extra buffer headers are available, leave the 44945116Smckusick * extra space in the present buffer. 45045116Smckusick */ 45145116Smckusick if (sizealloc < tp->b_bufsize) { 45245116Smckusick ep = bfreelist[BQ_EMPTY].av_forw; 45345116Smckusick if (ep == &bfreelist[BQ_EMPTY]) 45445116Smckusick goto out; 45545116Smckusick s = splbio(); 45645116Smckusick bremfree(ep); 45745116Smckusick ep->b_flags |= B_BUSY; 45845116Smckusick splx(s); 45945116Smckusick pagemove(tp->b_un.b_addr + sizealloc, ep->b_un.b_addr, 46045116Smckusick (int)tp->b_bufsize - sizealloc); 46145116Smckusick ep->b_bufsize = tp->b_bufsize - sizealloc; 46245116Smckusick tp->b_bufsize = sizealloc; 46345116Smckusick ep->b_flags |= B_INVAL; 46445116Smckusick ep->b_bcount = 0; 46545116Smckusick brelse(ep); 46645116Smckusick goto out; 46745116Smckusick } 46845116Smckusick /* 46945116Smckusick * More buffer space is needed. Get it out of buffers on 47045116Smckusick * the "most free" list, placing the empty headers on the 47145116Smckusick * BQ_EMPTY buffer header list. 47245116Smckusick */ 47345116Smckusick while (tp->b_bufsize < sizealloc) { 47445116Smckusick take = sizealloc - tp->b_bufsize; 47545116Smckusick bp = getnewbuf(); 47645116Smckusick if (take >= bp->b_bufsize) 47745116Smckusick take = bp->b_bufsize; 47845116Smckusick pagemove(&bp->b_un.b_addr[bp->b_bufsize - take], 47945116Smckusick &tp->b_un.b_addr[tp->b_bufsize], take); 48045116Smckusick tp->b_bufsize += take; 48145116Smckusick bp->b_bufsize = bp->b_bufsize - take; 48245116Smckusick if (bp->b_bcount > bp->b_bufsize) 48345116Smckusick bp->b_bcount = bp->b_bufsize; 48445116Smckusick if (bp->b_bufsize <= 0) { 48545116Smckusick bremhash(bp); 48645116Smckusick binshash(bp, &bfreelist[BQ_EMPTY]); 48746151Smckusick bp->b_dev = NODEV; 48845116Smckusick bp->b_error = 0; 48945116Smckusick bp->b_flags |= B_INVAL; 49045116Smckusick } 49145116Smckusick brelse(bp); 49245116Smckusick } 49345116Smckusick out: 49445116Smckusick tp->b_bcount = size; 49545116Smckusick return (1); 4968670S } 4978670S 4988670S /* 4998670S * Find a buffer which is available for use. 5008670S * Select something from a free list. 5018670S * Preference is to AGE list, then LRU list. 5028670S */ 5038670S struct buf * 5048670S getnewbuf() 5058670S { 5068670S register struct buf *bp, *dp; 50738776Smckusick register struct ucred *cred; 5088670S int s; 5098670S 51052096Sbostic #ifdef LFS 51152096Sbostic lfs_flush(); 51252096Sbostic #endif 5138670S loop: 51426271Skarels s = splbio(); 5158670S for (dp = &bfreelist[BQ_AGE]; dp > bfreelist; dp--) 5168670S if (dp->av_forw != dp) 5178670S break; 5188670S if (dp == bfreelist) { /* no free blocks */ 5198670S dp->b_flags |= B_WANTED; 52046151Smckusick sleep((caddr_t)dp, PRIBIO + 1); 52112170Ssam splx(s); 5228670S goto loop; 5238670S } 52439882Smckusick bp = dp->av_forw; 52539882Smckusick bremfree(bp); 52639882Smckusick bp->b_flags |= B_BUSY; 5278670S splx(s); 5288670S if (bp->b_flags & B_DELWRI) { 52938614Smckusick (void) bawrite(bp); 5308670S goto loop; 5318670S } 53240341Smckusick trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno); 53339668Smckusick if (bp->b_vp) 53439668Smckusick brelvp(bp); 53538776Smckusick if (bp->b_rcred != NOCRED) { 53638776Smckusick cred = bp->b_rcred; 53738776Smckusick bp->b_rcred = NOCRED; 53838776Smckusick crfree(cred); 53938776Smckusick } 54038776Smckusick if (bp->b_wcred != NOCRED) { 54138776Smckusick cred = bp->b_wcred; 54238776Smckusick bp->b_wcred = NOCRED; 54338776Smckusick crfree(cred); 54438776Smckusick } 5458670S bp->b_flags = B_BUSY; 54646989Smckusick bp->b_dirtyoff = bp->b_dirtyend = 0; 547*52189Smckusick bp->b_validoff = bp->b_validend = 0; 5488670S return (bp); 5498670S } 5508670S 5518670S /* 55246151Smckusick * Wait for I/O to complete. 55346151Smckusick * 55446151Smckusick * Extract and return any errors associated with the I/O. 55546151Smckusick * If the error flag is set, but no specific error is 55646151Smckusick * given, return EIO. 5578Sbill */ 5587015Smckusick biowait(bp) 5596563Smckusic register struct buf *bp; 5608Sbill { 5615431Sroot int s; 5628Sbill 56326271Skarels s = splbio(); 56438776Smckusick while ((bp->b_flags & B_DONE) == 0) 5658Sbill sleep((caddr_t)bp, PRIBIO); 5665431Sroot splx(s); 56737736Smckusick if ((bp->b_flags & B_ERROR) == 0) 56837736Smckusick return (0); 56937736Smckusick if (bp->b_error) 57037736Smckusick return (bp->b_error); 57137736Smckusick return (EIO); 5728Sbill } 5738Sbill 5748Sbill /* 57513128Ssam * Mark I/O complete on a buffer. 57646151Smckusick * 57746151Smckusick * If a callback has been requested, e.g. the pageout 57846151Smckusick * daemon, do so. Otherwise, awaken waiting processes. 5798Sbill */ 58051455Sbostic void 5817015Smckusick biodone(bp) 5827015Smckusick register struct buf *bp; 5838Sbill { 5848Sbill 585420Sbill if (bp->b_flags & B_DONE) 5867015Smckusick panic("dup biodone"); 5878Sbill bp->b_flags |= B_DONE; 58849232Smckusick if ((bp->b_flags & B_READ) == 0) 58949232Smckusick vwakeup(bp); 5909763Ssam if (bp->b_flags & B_CALL) { 5919763Ssam bp->b_flags &= ~B_CALL; 5929763Ssam (*bp->b_iodone)(bp); 5939763Ssam return; 5949763Ssam } 59546151Smckusick if (bp->b_flags & B_ASYNC) 5968Sbill brelse(bp); 5978Sbill else { 5988Sbill bp->b_flags &= ~B_WANTED; 5998Sbill wakeup((caddr_t)bp); 6008Sbill } 6018Sbill } 602