123395Smckusick /* 2*37736Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3*37736Smckusick * All rights reserved. 423395Smckusick * 5*37736Smckusick * Redistribution and use in source and binary forms are permitted 6*37736Smckusick * provided that the above copyright notice and this paragraph are 7*37736Smckusick * duplicated in all such forms and that any documentation, 8*37736Smckusick * advertising materials, and other materials related to such 9*37736Smckusick * distribution and use acknowledge that the software was developed 10*37736Smckusick * by the University of California, Berkeley. The name of the 11*37736Smckusick * University may not be used to endorse or promote products derived 12*37736Smckusick * from this software without specific prior written permission. 13*37736Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*37736Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*37736Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16*37736Smckusick * 17*37736Smckusick * @(#)vfs_cluster.c 7.5 (Berkeley) 05/09/89 1823395Smckusick */ 198Sbill 2017098Sbloom #include "param.h" 2117098Sbloom #include "user.h" 2217098Sbloom #include "buf.h" 23*37736Smckusick #include "vnode.h" 2417098Sbloom #include "trace.h" 258Sbill 2691Sbill /* 278Sbill * Read in (if necessary) the block and return a buffer pointer. 288Sbill */ 29*37736Smckusick bread(vp, blkno, size, bpp) 30*37736Smckusick struct vnode *vp; 316563Smckusic daddr_t blkno; 326563Smckusic int size; 33*37736Smckusick struct buf **bpp; 348Sbill { 358Sbill register struct buf *bp; 368Sbill 378670S if (size == 0) 388670S panic("bread: size 0"); 39*37736Smckusick *bpp = bp = getblk(vp, blkno, size); 4032608Smckusick if (bp->b_flags&(B_DONE|B_DELWRI)) { 41*37736Smckusick trace(TR_BREADHIT, pack(vp->v_mount->m_fsid[0], size), blkno); 42*37736Smckusick return (0); 438Sbill } 448Sbill bp->b_flags |= B_READ; 458670S if (bp->b_bcount > bp->b_bufsize) 468670S panic("bread"); 47*37736Smckusick VOP_STRATEGY(bp); 48*37736Smckusick trace(TR_BREADMISS, pack(vp->v_mount->m_fsid[0], size), blkno); 498039Sroot u.u_ru.ru_inblock++; /* pay for read */ 50*37736Smckusick return (biowait(bp)); 518Sbill } 528Sbill 538Sbill /* 548Sbill * Read in the block, like bread, but also start I/O on the 558Sbill * read-ahead block (which is not allocated to the caller) 568Sbill */ 57*37736Smckusick breada(vp, blkno, size, rablkno, rabsize, bpp) 58*37736Smckusick struct vnode *vp; 597114Smckusick daddr_t blkno; int size; 608592Sroot daddr_t rablkno; int rabsize; 61*37736Smckusick struct buf **bpp; 628Sbill { 638Sbill register struct buf *bp, *rabp; 648Sbill 658Sbill bp = NULL; 667015Smckusick /* 677015Smckusick * If the block isn't in core, then allocate 687015Smckusick * a buffer and initiate i/o (getblk checks 697015Smckusick * for a cache hit). 707015Smckusick */ 71*37736Smckusick if (!incore(vp, blkno)) { 72*37736Smckusick *bpp = bp = getblk(vp, blkno, size); 7332608Smckusick if ((bp->b_flags&(B_DONE|B_DELWRI)) == 0) { 748Sbill bp->b_flags |= B_READ; 758670S if (bp->b_bcount > bp->b_bufsize) 768670S panic("breada"); 77*37736Smckusick VOP_STRATEGY(bp); 78*37736Smckusick trace(TR_BREADMISS, pack(vp->v_mount->m_fsid[0], size), 79*37736Smckusick blkno); 808039Sroot u.u_ru.ru_inblock++; /* pay for read */ 817015Smckusick } else 82*37736Smckusick trace(TR_BREADHIT, pack(vp->v_mount->m_fsid[0], size), 83*37736Smckusick blkno); 848Sbill } 857015Smckusick 867015Smckusick /* 877015Smckusick * If there's a read-ahead block, start i/o 887015Smckusick * on it also (as above). 897015Smckusick */ 90*37736Smckusick if (rablkno && !incore(vp, rablkno)) { 91*37736Smckusick rabp = getblk(vp, rablkno, rabsize); 9232608Smckusick if (rabp->b_flags & (B_DONE|B_DELWRI)) { 938Sbill brelse(rabp); 94*37736Smckusick trace(TR_BREADHITRA, 95*37736Smckusick pack(vp->v_mount->m_fsid[0], rabsize), blkno); 962045Swnj } else { 978Sbill rabp->b_flags |= B_READ|B_ASYNC; 988670S if (rabp->b_bcount > rabp->b_bufsize) 998670S panic("breadrabp"); 100*37736Smckusick VOP_STRATEGY(rabp); 101*37736Smckusick trace(TR_BREADMISSRA, 102*37736Smckusick pack(vp->v_mount->m_fsid[0], rabsize), rablock); 1038039Sroot u.u_ru.ru_inblock++; /* pay in advance */ 1048Sbill } 1058Sbill } 1067015Smckusick 1077015Smckusick /* 1087114Smckusick * If block was in core, let bread get it. 1097114Smckusick * If block wasn't in core, then the read was started 1107114Smckusick * above, and just wait for it. 1117015Smckusick */ 1127114Smckusick if (bp == NULL) 113*37736Smckusick return (bread(vp, blkno, size, bpp)); 114*37736Smckusick return (biowait(bp)); 1158Sbill } 1168Sbill 1178Sbill /* 1188Sbill * Write the buffer, waiting for completion. 1198Sbill * Then release the buffer. 1208Sbill */ 1218Sbill bwrite(bp) 1227015Smckusick register struct buf *bp; 1238Sbill { 124*37736Smckusick register int flag; 125*37736Smckusick int error; 1268Sbill 1278Sbill flag = bp->b_flags; 1289857Ssam bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI); 1298Sbill if ((flag&B_DELWRI) == 0) 1308039Sroot u.u_ru.ru_oublock++; /* noone paid yet */ 131*37736Smckusick trace(TR_BWRITE, 132*37736Smckusick pack(bp->b_vp->v_mount->m_fsid[0], bp->b_bcount), bp->b_blkno); 1338670S if (bp->b_bcount > bp->b_bufsize) 1348670S panic("bwrite"); 135*37736Smckusick VOP_STRATEGY(bp); 1367015Smckusick 1377015Smckusick /* 1387015Smckusick * If the write was synchronous, then await i/o completion. 1397015Smckusick * If the write was "delayed", then we put the buffer on 1407015Smckusick * the q of blocks awaiting i/o completion status. 1417015Smckusick */ 1428Sbill if ((flag&B_ASYNC) == 0) { 143*37736Smckusick error = biowait(bp); 1448Sbill brelse(bp); 145*37736Smckusick } else if (flag & B_DELWRI) { 1468Sbill bp->b_flags |= B_AGE; 147*37736Smckusick error = 0; 148*37736Smckusick } 149*37736Smckusick return (error); 1508Sbill } 1518Sbill 1528Sbill /* 1538Sbill * Release the buffer, marking it so that if it is grabbed 1548Sbill * for another purpose it will be written out before being 1558Sbill * given up (e.g. when writing a partial block where it is 1568Sbill * assumed that another write for the same block will soon follow). 1578Sbill * This can't be done for magtape, since writes must be done 1588Sbill * in the same order as requested. 1598Sbill */ 1608Sbill bdwrite(bp) 1617015Smckusick register struct buf *bp; 1628Sbill { 1638Sbill 1648Sbill if ((bp->b_flags&B_DELWRI) == 0) 1658039Sroot u.u_ru.ru_oublock++; /* noone paid yet */ 166*37736Smckusick #ifdef notdef 167*37736Smckusick /* 168*37736Smckusick * This does not work for buffers associated with 169*37736Smckusick * vnodes that are remote - they have no dev. 170*37736Smckusick * Besides, we don't use bio with tapes, so rather 171*37736Smckusick * than develop a fix, we just ifdef this out for now. 172*37736Smckusick */ 17330749Skarels if (bdevsw[major(bp->b_dev)].d_flags & B_TAPE) 1748Sbill bawrite(bp); 1758Sbill else { 1768Sbill bp->b_flags |= B_DELWRI | B_DONE; 1778Sbill brelse(bp); 1788Sbill } 179*37736Smckusick #endif 180*37736Smckusick bp->b_flags |= B_DELWRI | B_DONE; 181*37736Smckusick brelse(bp); 1828Sbill } 1838Sbill 1848Sbill /* 1858Sbill * Release the buffer, start I/O on it, but don't wait for completion. 1868Sbill */ 1878Sbill bawrite(bp) 1887015Smckusick register struct buf *bp; 1898Sbill { 1908Sbill 1918Sbill bp->b_flags |= B_ASYNC; 192*37736Smckusick (void) bwrite(bp); 1938Sbill } 1948Sbill 1958Sbill /* 1967015Smckusick * Release the buffer, with no I/O implied. 1978Sbill */ 1988Sbill brelse(bp) 1997015Smckusick register struct buf *bp; 2008Sbill { 2012325Swnj register struct buf *flist; 2028Sbill register s; 2038Sbill 204*37736Smckusick trace(TR_BRELSE, 205*37736Smckusick pack(bp->b_vp->v_mount->m_fsid[0], bp->b_bufsize), bp->b_blkno); 2067015Smckusick /* 2077015Smckusick * If someone's waiting for the buffer, or 2087015Smckusick * is waiting for a buffer wake 'em up. 2097015Smckusick */ 2108Sbill if (bp->b_flags&B_WANTED) 2118Sbill wakeup((caddr_t)bp); 2122325Swnj if (bfreelist[0].b_flags&B_WANTED) { 2132325Swnj bfreelist[0].b_flags &= ~B_WANTED; 2142325Swnj wakeup((caddr_t)bfreelist); 2158Sbill } 216*37736Smckusick if (bp->b_flags & B_NOCACHE) { 217*37736Smckusick bp->b_flags |= B_INVAL; 218*37736Smckusick } 2192683Swnj if (bp->b_flags&B_ERROR) 2202683Swnj if (bp->b_flags & B_LOCKED) 2212683Swnj bp->b_flags &= ~B_ERROR; /* try again later */ 2222683Swnj else 223*37736Smckusick brelvp(bp); /* no assoc */ 2247015Smckusick 2257015Smckusick /* 2267015Smckusick * Stick the buffer back on a free list. 2277015Smckusick */ 22826271Skarels s = splbio(); 2298670S if (bp->b_bufsize <= 0) { 2308670S /* block has no buffer ... put at front of unused buffer list */ 2318670S flist = &bfreelist[BQ_EMPTY]; 2328670S binsheadfree(bp, flist); 2338670S } else if (bp->b_flags & (B_ERROR|B_INVAL)) { 2342325Swnj /* block has no info ... put at front of most free list */ 2358670S flist = &bfreelist[BQ_AGE]; 2367015Smckusick binsheadfree(bp, flist); 2378Sbill } else { 2382325Swnj if (bp->b_flags & B_LOCKED) 2392325Swnj flist = &bfreelist[BQ_LOCKED]; 2402325Swnj else if (bp->b_flags & B_AGE) 2412325Swnj flist = &bfreelist[BQ_AGE]; 2422325Swnj else 2432325Swnj flist = &bfreelist[BQ_LRU]; 2447015Smckusick binstailfree(bp, flist); 2458Sbill } 246*37736Smckusick bp->b_flags &= ~(B_WANTED|B_BUSY|B_ASYNC|B_AGE|B_NOCACHE); 2478Sbill splx(s); 2488Sbill } 2498Sbill 2508Sbill /* 2518Sbill * See if the block is associated with some buffer 2528Sbill * (mainly to avoid getting hung up on a wait in breada) 2538Sbill */ 254*37736Smckusick incore(vp, blkno) 255*37736Smckusick struct vnode *vp; 2567015Smckusick daddr_t blkno; 2578Sbill { 2588Sbill register struct buf *bp; 2592325Swnj register struct buf *dp; 2608Sbill 261*37736Smckusick dp = BUFHASH(vp->v_rdev, blkno); 2622325Swnj for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) 263*37736Smckusick if (bp->b_blkno == blkno && bp->b_vp == vp && 2647015Smckusick (bp->b_flags & B_INVAL) == 0) 26591Sbill return (1); 26691Sbill return (0); 2678Sbill } 2688Sbill 269*37736Smckusick baddr(vp, blkno, size, bpp) 270*37736Smckusick struct vnode *vp; 2716563Smckusic daddr_t blkno; 2726563Smckusic int size; 273*37736Smckusick struct buf **bpp; 2748Sbill { 2758Sbill 276*37736Smckusick if (incore(vp, blkno)) 277*37736Smckusick return (bread(vp, blkno, size, bpp)); 278*37736Smckusick *bpp = 0; 2798Sbill return (0); 2808Sbill } 2818Sbill 2828Sbill /* 2838Sbill * Assign a buffer for the given block. If the appropriate 2848Sbill * block is already associated, return it; otherwise search 2858Sbill * for the oldest non-busy buffer and reassign it. 2865424Swnj * 28732608Smckusick * If we find the buffer, but it is dirty (marked DELWRI) and 28832608Smckusick * its size is changing, we must write it out first. When the 28932608Smckusick * buffer is shrinking, the write is done by brealloc to avoid 29032608Smckusick * losing the unwritten data. When the buffer is growing, the 29132608Smckusick * write is done by getblk, so that bread will not read stale 29232608Smckusick * disk data over the modified data in the buffer. 29332608Smckusick * 2945424Swnj * We use splx here because this routine may be called 2955424Swnj * on the interrupt stack during a dump, and we don't 2965424Swnj * want to lower the ipl back to 0. 2978Sbill */ 2988Sbill struct buf * 299*37736Smckusick getblk(vp, blkno, size) 300*37736Smckusick register struct vnode *vp; 3016563Smckusic daddr_t blkno; 3026563Smckusic int size; 3038Sbill { 3048670S register struct buf *bp, *dp; 3055424Swnj int s; 3068Sbill 30725255Smckusick if (size > MAXBSIZE) 30825255Smckusick panic("getblk: size too big"); 3097015Smckusick /* 31024730Smckusick * To prevent overflow of 32-bit ints when converting block 31124730Smckusick * numbers to byte offsets, blknos > 2^32 / DEV_BSIZE are set 31224730Smckusick * to the maximum number that can be converted to a byte offset 31324730Smckusick * without overflow. This is historic code; what bug it fixed, 31424730Smckusick * or whether it is still a reasonable thing to do is open to 31524730Smckusick * dispute. mkm 9/85 31624730Smckusick */ 31724730Smckusick if ((unsigned)blkno >= 1 << (sizeof(int)*NBBY-DEV_BSHIFT)) 31824730Smckusick blkno = 1 << ((sizeof(int)*NBBY-DEV_BSHIFT) + 1); 31924730Smckusick /* 3207015Smckusick * Search the cache for the block. If we hit, but 3217015Smckusick * the buffer is in use for i/o, then we wait until 3227015Smckusick * the i/o has completed. 3237015Smckusick */ 324*37736Smckusick dp = BUFHASH(vp, blkno); 3257015Smckusick loop: 3262325Swnj for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) { 327*37736Smckusick if (bp->b_blkno != blkno || bp->b_vp != vp || 3282325Swnj bp->b_flags&B_INVAL) 3298Sbill continue; 33026271Skarels s = splbio(); 3318Sbill if (bp->b_flags&B_BUSY) { 3328Sbill bp->b_flags |= B_WANTED; 3338Sbill sleep((caddr_t)bp, PRIBIO+1); 3345424Swnj splx(s); 3358Sbill goto loop; 3368Sbill } 3375424Swnj splx(s); 3388Sbill notavail(bp); 33932608Smckusick if (bp->b_bcount != size) { 34032608Smckusick if (bp->b_bcount < size && (bp->b_flags&B_DELWRI)) { 34132608Smckusick bp->b_flags &= ~B_ASYNC; 342*37736Smckusick (void) bwrite(bp); 34332608Smckusick goto loop; 34432608Smckusick } 34532608Smckusick if (brealloc(bp, size) == 0) 34632608Smckusick goto loop; 34732608Smckusick } 34816855Smckusick if (bp->b_bcount != size && brealloc(bp, size) == 0) 3497188Sroot goto loop; 3508Sbill bp->b_flags |= B_CACHE; 35126271Skarels return (bp); 3528Sbill } 3538670S bp = getnewbuf(); 3546563Smckusic bfree(bp); 3557015Smckusick bremhash(bp); 356*37736Smckusick if (bp->b_vp) 357*37736Smckusick brelvp(bp); 358*37736Smckusick vp->v_count++; 359*37736Smckusick bp->b_vp = vp; 360*37736Smckusick bp->b_dev = vp->v_rdev; 3616563Smckusic bp->b_blkno = blkno; 3628670S bp->b_error = 0; 363*37736Smckusick bp->b_resid = 0; 364*37736Smckusick binshash(bp, dp); 3657188Sroot if (brealloc(bp, size) == 0) 3667188Sroot goto loop; 36726271Skarels return (bp); 3688Sbill } 3698Sbill 3708Sbill /* 3718Sbill * get an empty block, 3728Sbill * not assigned to any particular device 3738Sbill */ 3748Sbill struct buf * 3756563Smckusic geteblk(size) 3766563Smckusic int size; 3778Sbill { 3788670S register struct buf *bp, *flist; 3798Sbill 38025255Smckusick if (size > MAXBSIZE) 38125255Smckusick panic("geteblk: size too big"); 3828Sbill loop: 3838670S bp = getnewbuf(); 3848670S bp->b_flags |= B_INVAL; 3857015Smckusick bfree(bp); 3867015Smckusick bremhash(bp); 3878670S flist = &bfreelist[BQ_AGE]; 388*37736Smckusick brelvp(bp); 389*37736Smckusick bp->b_error = 0; 390*37736Smckusick bp->b_resid = 0; 3918670S binshash(bp, flist); 3927188Sroot if (brealloc(bp, size) == 0) 3937188Sroot goto loop; 39426271Skarels return (bp); 3958Sbill } 3968Sbill 3978Sbill /* 3986563Smckusic * Allocate space associated with a buffer. 3999763Ssam * If can't get space, buffer is released 4006563Smckusic */ 4016563Smckusic brealloc(bp, size) 4026563Smckusic register struct buf *bp; 4036563Smckusic int size; 4046563Smckusic { 4056563Smckusic daddr_t start, last; 4066563Smckusic register struct buf *ep; 4076563Smckusic struct buf *dp; 4086563Smckusic int s; 4096563Smckusic 4106563Smckusic /* 41130749Skarels * First need to make sure that all overlapping previous I/O 4126563Smckusic * is dispatched with. 4136563Smckusic */ 4146563Smckusic if (size == bp->b_bcount) 4157188Sroot return (1); 4167188Sroot if (size < bp->b_bcount) { 4177188Sroot if (bp->b_flags & B_DELWRI) { 418*37736Smckusick (void) bwrite(bp); 4197188Sroot return (0); 4207188Sroot } 4217188Sroot if (bp->b_flags & B_LOCKED) 4227188Sroot panic("brealloc"); 4239763Ssam return (allocbuf(bp, size)); 4247188Sroot } 4257188Sroot bp->b_flags &= ~B_DONE; 426*37736Smckusick if (bp->b_vp == (struct vnode *)0) 4279763Ssam return (allocbuf(bp, size)); 4287016Smckusick 429*37736Smckusick trace(TR_BREALLOC, 430*37736Smckusick pack(bp->b_vp->v_mount->m_fsid[0], size), bp->b_blkno); 4317188Sroot /* 4327188Sroot * Search cache for any buffers that overlap the one that we 4337188Sroot * are trying to allocate. Overlapping buffers must be marked 4347188Sroot * invalid, after being written out if they are dirty. (indicated 4357188Sroot * by B_DELWRI) A disk block must be mapped by at most one buffer 4367188Sroot * at any point in time. Care must be taken to avoid deadlocking 4377188Sroot * when two buffer are trying to get the same set of disk blocks. 4387188Sroot */ 4397188Sroot start = bp->b_blkno; 44012644Ssam last = start + btodb(size) - 1; 441*37736Smckusick dp = BUFHASH(bp->b_vp, bp->b_blkno); 4426563Smckusic loop: 4436563Smckusic for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) { 444*37736Smckusick if (ep == bp || ep->b_vp != bp->b_vp || 445*37736Smckusick (ep->b_flags & B_INVAL)) 4466563Smckusic continue; 4477188Sroot /* look for overlap */ 4487188Sroot if (ep->b_bcount == 0 || ep->b_blkno > last || 44912644Ssam ep->b_blkno + btodb(ep->b_bcount) <= start) 4507188Sroot continue; 45126271Skarels s = splbio(); 4526563Smckusic if (ep->b_flags&B_BUSY) { 4536563Smckusic ep->b_flags |= B_WANTED; 4546563Smckusic sleep((caddr_t)ep, PRIBIO+1); 4558670S splx(s); 4566563Smckusic goto loop; 4576563Smckusic } 4588670S splx(s); 4597188Sroot notavail(ep); 4606563Smckusic if (ep->b_flags & B_DELWRI) { 461*37736Smckusick (void) bwrite(ep); 4626563Smckusic goto loop; 4636563Smckusic } 4647188Sroot ep->b_flags |= B_INVAL; 4657188Sroot brelse(ep); 4666563Smckusic } 4679763Ssam return (allocbuf(bp, size)); 4688670S } 4698670S 4708670S /* 4718670S * Find a buffer which is available for use. 4728670S * Select something from a free list. 4738670S * Preference is to AGE list, then LRU list. 4748670S */ 4758670S struct buf * 4768670S getnewbuf() 4778670S { 4788670S register struct buf *bp, *dp; 4798670S int s; 4808670S 4818670S loop: 48226271Skarels s = splbio(); 4838670S for (dp = &bfreelist[BQ_AGE]; dp > bfreelist; dp--) 4848670S if (dp->av_forw != dp) 4858670S break; 4868670S if (dp == bfreelist) { /* no free blocks */ 4878670S dp->b_flags |= B_WANTED; 4888670S sleep((caddr_t)dp, PRIBIO+1); 48912170Ssam splx(s); 4908670S goto loop; 4918670S } 4928670S splx(s); 4938670S bp = dp->av_forw; 4948670S notavail(bp); 4958670S if (bp->b_flags & B_DELWRI) { 4968670S bp->b_flags |= B_ASYNC; 497*37736Smckusick (void) bwrite(bp); 4988670S goto loop; 4998670S } 500*37736Smckusick trace(TR_BRELSE, 501*37736Smckusick pack(bp->b_vp->v_mount->m_fsid[0], bp->b_bufsize), bp->b_blkno); 502*37736Smckusick brelvp(bp); 5038670S bp->b_flags = B_BUSY; 5048670S return (bp); 5058670S } 5068670S 5078670S /* 5088Sbill * Wait for I/O completion on the buffer; return errors 5098Sbill * to the user. 5108Sbill */ 5117015Smckusick biowait(bp) 5126563Smckusic register struct buf *bp; 5138Sbill { 5145431Sroot int s; 5158Sbill 51626271Skarels s = splbio(); 5178Sbill while ((bp->b_flags&B_DONE)==0) 5188Sbill sleep((caddr_t)bp, PRIBIO); 5195431Sroot splx(s); 520*37736Smckusick /* 521*37736Smckusick * Pick up the device's error number and pass it to the user; 522*37736Smckusick * if there is an error but the number is 0 set a generalized code. 523*37736Smckusick */ 524*37736Smckusick if ((bp->b_flags & B_ERROR) == 0) 525*37736Smckusick return (0); 526*37736Smckusick if (bp->b_error) 527*37736Smckusick return (bp->b_error); 528*37736Smckusick return (EIO); 5298Sbill } 5308Sbill 5318Sbill /* 53213128Ssam * Mark I/O complete on a buffer. 53313128Ssam * If someone should be called, e.g. the pageout 53413128Ssam * daemon, do so. Otherwise, wake up anyone 53513128Ssam * waiting for it. 5368Sbill */ 5377015Smckusick biodone(bp) 5387015Smckusick register struct buf *bp; 5398Sbill { 5408Sbill 541420Sbill if (bp->b_flags & B_DONE) 5427015Smckusick panic("dup biodone"); 5438Sbill bp->b_flags |= B_DONE; 5449763Ssam if (bp->b_flags & B_CALL) { 5459763Ssam bp->b_flags &= ~B_CALL; 5469763Ssam (*bp->b_iodone)(bp); 5479763Ssam return; 5489763Ssam } 5498Sbill if (bp->b_flags&B_ASYNC) 5508Sbill brelse(bp); 5518Sbill else { 5528Sbill bp->b_flags &= ~B_WANTED; 5538Sbill wakeup((caddr_t)bp); 5548Sbill } 5558Sbill } 5568Sbill 5578Sbill /* 558*37736Smckusick * Ensure that no part of a specified block is in an incore buffer. 55930749Skarels #ifdef SECSIZE 56030749Skarels * "size" is given in device blocks (the units of b_blkno). 56130749Skarels #endif SECSIZE 5628670S */ 563*37736Smckusick blkflush(vp, blkno, size) 564*37736Smckusick struct vnode *vp; 5658670S daddr_t blkno; 5668670S long size; 5678670S { 5688670S register struct buf *ep; 5698670S struct buf *dp; 5708670S daddr_t start, last; 571*37736Smckusick int s, error, allerrors = 0; 5728670S 5738670S start = blkno; 57412644Ssam last = start + btodb(size) - 1; 575*37736Smckusick dp = BUFHASH(vp, blkno); 5768670S loop: 5778670S for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) { 578*37736Smckusick if (ep->b_vp != vp || (ep->b_flags & B_INVAL)) 5798670S continue; 5808670S /* look for overlap */ 5818670S if (ep->b_bcount == 0 || ep->b_blkno > last || 58212644Ssam ep->b_blkno + btodb(ep->b_bcount) <= start) 5838670S continue; 58426271Skarels s = splbio(); 5858670S if (ep->b_flags&B_BUSY) { 5868670S ep->b_flags |= B_WANTED; 5878670S sleep((caddr_t)ep, PRIBIO+1); 5888670S splx(s); 5898670S goto loop; 5908670S } 5918670S if (ep->b_flags & B_DELWRI) { 5928670S splx(s); 5938670S notavail(ep); 594*37736Smckusick if (error = bwrite(ep)) 595*37736Smckusick allerrors = error; 5968670S goto loop; 5978670S } 5988670S splx(s); 5998670S } 600*37736Smckusick return (allerrors); 6018670S } 6028670S 6038670S /* 604*37736Smckusick * Make sure all write-behind blocks associated 605*37736Smckusick * with vp are flushed out (from sync). 6068Sbill */ 6078Sbill bflush(dev) 6087015Smckusick dev_t dev; 6098Sbill { 6108Sbill register struct buf *bp; 6112325Swnj register struct buf *flist; 6125431Sroot int s; 6138Sbill 6148Sbill loop: 61526271Skarels s = splbio(); 6168670S for (flist = bfreelist; flist < &bfreelist[BQ_EMPTY]; flist++) 6172325Swnj for (bp = flist->av_forw; bp != flist; bp = bp->av_forw) { 6187015Smckusick if ((bp->b_flags & B_DELWRI) == 0) 6197015Smckusick continue; 6207015Smckusick if (dev == NODEV || dev == bp->b_dev) { 6218Sbill bp->b_flags |= B_ASYNC; 6228Sbill notavail(bp); 623*37736Smckusick (void) bwrite(bp); 62412173Ssam splx(s); 6258Sbill goto loop; 6268Sbill } 6278Sbill } 6285431Sroot splx(s); 6298Sbill } 6308Sbill 631*37736Smckusick #ifdef unused 6328Sbill /* 633*37736Smckusick * Invalidate blocks associated with vp which are on the freelist. 634*37736Smckusick * Make sure all write-behind blocks associated with vp are flushed out. 6358Sbill */ 636*37736Smckusick binvalfree(vp) 637*37736Smckusick struct vnode *vp; 638*37736Smckusick { 6397015Smckusick register struct buf *bp; 640*37736Smckusick register struct buf *flist; 641*37736Smckusick int s; 6428Sbill 643*37736Smckusick loop: 644*37736Smckusick s = splbio(); 645*37736Smckusick for (flist = bfreelist; flist < &bfreelist[BQ_EMPTY]; flist++) 646*37736Smckusick for (bp = flist->av_forw; bp != flist; bp = bp->av_forw) { 647*37736Smckusick if (vp == (struct vnode *) 0 || vp == bp->b_vp) { 648*37736Smckusick if (bp->b_flags & B_DELWRI) { 649*37736Smckusick bp->b_flags |= B_ASYNC; 650*37736Smckusick notavail(bp); 651*37736Smckusick (void) splx(s); 652*37736Smckusick (void) bwrite(bp); 653*37736Smckusick } else { 654*37736Smckusick bp->b_flags |= B_INVAL; 655*37736Smckusick brelvp(bp); 656*37736Smckusick (void) splx(s); 657*37736Smckusick } 658*37736Smckusick goto loop; 659*37736Smckusick } 660*37736Smckusick } 661*37736Smckusick (void) splx(s); 6628Sbill } 663*37736Smckusick #endif /* unused */ 6642299Skre 6652299Skre /* 6662299Skre * Invalidate in core blocks belonging to closed or umounted filesystem 6672299Skre * 6682299Skre * This is not nicely done at all - the buffer ought to be removed from the 6692299Skre * hash chains & have its dev/blkno fields clobbered, but unfortunately we 6702299Skre * can't do that here, as it is quite possible that the block is still 6712299Skre * being used for i/o. Eventually, all disc drivers should be forced to 6722299Skre * have a close routine, which ought ensure that the queue is empty, then 6732299Skre * properly flush the queues. Until that happy day, this suffices for 6742299Skre * correctness. ... kre 6752299Skre */ 6762299Skre binval(dev) 6777015Smckusick dev_t dev; 6782299Skre { 6792361Skre register struct buf *bp; 6802361Skre register struct bufhd *hp; 6812361Skre #define dp ((struct buf *)hp) 6822299Skre 683*37736Smckusick loop: 6842361Skre for (hp = bufhash; hp < &bufhash[BUFHSZ]; hp++) 6852361Skre for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) 686*37736Smckusick if (bp->b_dev == dev && (bp->b_flags & B_INVAL) == 0) { 6872361Skre bp->b_flags |= B_INVAL; 688*37736Smckusick brelvp(bp); 689*37736Smckusick goto loop; 690*37736Smckusick } 6912299Skre } 692*37736Smckusick 693*37736Smckusick brelvp(bp) 694*37736Smckusick struct buf *bp; 695*37736Smckusick { 696*37736Smckusick struct vnode *vp; 697*37736Smckusick 698*37736Smckusick if (bp->b_vp == (struct vnode *) 0) 699*37736Smckusick return; 700*37736Smckusick vp = bp->b_vp; 701*37736Smckusick bp->b_vp = (struct vnode *) 0; 702*37736Smckusick vrele(vp); 703*37736Smckusick } 704