123395Smckusick /* 229114Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323395Smckusick * All rights reserved. The Berkeley software License Agreement 423395Smckusick * specifies the terms and conditions for redistribution. 523395Smckusick * 6*32608Smckusick * @(#)vfs_cluster.c 7.3 (Berkeley) 11/12/87 723395Smckusick */ 88Sbill 99763Ssam #include "../machine/pte.h" 109763Ssam 1117098Sbloom #include "param.h" 1217098Sbloom #include "systm.h" 1317098Sbloom #include "dir.h" 1417098Sbloom #include "user.h" 1517098Sbloom #include "buf.h" 1617098Sbloom #include "conf.h" 1717098Sbloom #include "proc.h" 1817098Sbloom #include "seg.h" 1917098Sbloom #include "vm.h" 2017098Sbloom #include "trace.h" 218Sbill 2291Sbill /* 238Sbill * Read in (if necessary) the block and return a buffer pointer. 248Sbill */ 258Sbill struct buf * 266563Smckusic bread(dev, blkno, size) 276563Smckusic dev_t dev; 286563Smckusic daddr_t blkno; 296563Smckusic int size; 308Sbill { 318Sbill register struct buf *bp; 328Sbill 338670S if (size == 0) 348670S panic("bread: size 0"); 356563Smckusic bp = getblk(dev, blkno, size); 36*32608Smckusick if (bp->b_flags&(B_DONE|B_DELWRI)) { 3715795Ssam trace(TR_BREADHIT, pack(dev, size), blkno); 3826271Skarels return (bp); 398Sbill } 408Sbill bp->b_flags |= B_READ; 418670S if (bp->b_bcount > bp->b_bufsize) 428670S panic("bread"); 438Sbill (*bdevsw[major(dev)].d_strategy)(bp); 4415795Ssam trace(TR_BREADMISS, pack(dev, size), blkno); 458039Sroot u.u_ru.ru_inblock++; /* pay for read */ 467015Smckusick biowait(bp); 4726271Skarels return (bp); 488Sbill } 498Sbill 508Sbill /* 518Sbill * Read in the block, like bread, but also start I/O on the 528Sbill * read-ahead block (which is not allocated to the caller) 538Sbill */ 548Sbill struct buf * 558592Sroot breada(dev, blkno, size, rablkno, rabsize) 566563Smckusic dev_t dev; 577114Smckusick daddr_t blkno; int size; 588592Sroot daddr_t rablkno; int rabsize; 598Sbill { 608Sbill register struct buf *bp, *rabp; 618Sbill 628Sbill bp = NULL; 637015Smckusick /* 647015Smckusick * If the block isn't in core, then allocate 657015Smckusick * a buffer and initiate i/o (getblk checks 667015Smckusick * for a cache hit). 677015Smckusick */ 688Sbill if (!incore(dev, blkno)) { 696563Smckusic bp = getblk(dev, blkno, size); 70*32608Smckusick if ((bp->b_flags&(B_DONE|B_DELWRI)) == 0) { 718Sbill bp->b_flags |= B_READ; 728670S if (bp->b_bcount > bp->b_bufsize) 738670S panic("breada"); 748Sbill (*bdevsw[major(dev)].d_strategy)(bp); 7515795Ssam trace(TR_BREADMISS, pack(dev, size), blkno); 768039Sroot u.u_ru.ru_inblock++; /* pay for read */ 777015Smckusick } else 7815795Ssam trace(TR_BREADHIT, pack(dev, size), blkno); 798Sbill } 807015Smckusick 817015Smckusick /* 827015Smckusick * If there's a read-ahead block, start i/o 837015Smckusick * on it also (as above). 847015Smckusick */ 858Sbill if (rablkno && !incore(dev, rablkno)) { 868592Sroot rabp = getblk(dev, rablkno, rabsize); 87*32608Smckusick if (rabp->b_flags & (B_DONE|B_DELWRI)) { 888Sbill brelse(rabp); 8915795Ssam trace(TR_BREADHITRA, pack(dev, rabsize), blkno); 902045Swnj } else { 918Sbill rabp->b_flags |= B_READ|B_ASYNC; 928670S if (rabp->b_bcount > rabp->b_bufsize) 938670S panic("breadrabp"); 948Sbill (*bdevsw[major(dev)].d_strategy)(rabp); 9515795Ssam trace(TR_BREADMISSRA, pack(dev, rabsize), rablock); 968039Sroot u.u_ru.ru_inblock++; /* pay in advance */ 978Sbill } 988Sbill } 997015Smckusick 1007015Smckusick /* 1017114Smckusick * If block was in core, let bread get it. 1027114Smckusick * If block wasn't in core, then the read was started 1037114Smckusick * above, and just wait for it. 1047015Smckusick */ 1057114Smckusick if (bp == NULL) 1067114Smckusick return (bread(dev, blkno, size)); 1077015Smckusick biowait(bp); 1087114Smckusick return (bp); 1098Sbill } 1108Sbill 1118Sbill /* 1128Sbill * Write the buffer, waiting for completion. 1138Sbill * Then release the buffer. 1148Sbill */ 1158Sbill bwrite(bp) 1167015Smckusick register struct buf *bp; 1178Sbill { 1188Sbill register flag; 1198Sbill 1208Sbill flag = bp->b_flags; 1219857Ssam bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI); 1228Sbill if ((flag&B_DELWRI) == 0) 1238039Sroot u.u_ru.ru_oublock++; /* noone paid yet */ 12415795Ssam trace(TR_BWRITE, pack(bp->b_dev, bp->b_bcount), bp->b_blkno); 1258670S if (bp->b_bcount > bp->b_bufsize) 1268670S panic("bwrite"); 1278Sbill (*bdevsw[major(bp->b_dev)].d_strategy)(bp); 1287015Smckusick 1297015Smckusick /* 1307015Smckusick * If the write was synchronous, then await i/o completion. 1317015Smckusick * If the write was "delayed", then we put the buffer on 1327015Smckusick * the q of blocks awaiting i/o completion status. 1337015Smckusick */ 1348Sbill if ((flag&B_ASYNC) == 0) { 1357015Smckusick biowait(bp); 1368Sbill brelse(bp); 1378Sbill } else if (flag & B_DELWRI) 1388Sbill bp->b_flags |= B_AGE; 1398Sbill } 1408Sbill 1418Sbill /* 1428Sbill * Release the buffer, marking it so that if it is grabbed 1438Sbill * for another purpose it will be written out before being 1448Sbill * given up (e.g. when writing a partial block where it is 1458Sbill * assumed that another write for the same block will soon follow). 1468Sbill * This can't be done for magtape, since writes must be done 1478Sbill * in the same order as requested. 1488Sbill */ 1498Sbill bdwrite(bp) 1507015Smckusick register struct buf *bp; 1518Sbill { 1528Sbill 1538Sbill if ((bp->b_flags&B_DELWRI) == 0) 1548039Sroot u.u_ru.ru_oublock++; /* noone paid yet */ 15530749Skarels if (bdevsw[major(bp->b_dev)].d_flags & B_TAPE) 1568Sbill bawrite(bp); 1578Sbill else { 1588Sbill bp->b_flags |= B_DELWRI | B_DONE; 1598Sbill brelse(bp); 1608Sbill } 1618Sbill } 1628Sbill 1638Sbill /* 1648Sbill * Release the buffer, start I/O on it, but don't wait for completion. 1658Sbill */ 1668Sbill bawrite(bp) 1677015Smckusick register struct buf *bp; 1688Sbill { 1698Sbill 1708Sbill bp->b_flags |= B_ASYNC; 1718Sbill bwrite(bp); 1728Sbill } 1738Sbill 1748Sbill /* 1757015Smckusick * Release the buffer, with no I/O implied. 1768Sbill */ 1778Sbill brelse(bp) 1787015Smckusick register struct buf *bp; 1798Sbill { 1802325Swnj register struct buf *flist; 1818Sbill register s; 1828Sbill 18315795Ssam trace(TR_BRELSE, pack(bp->b_dev, bp->b_bufsize), bp->b_blkno); 1847015Smckusick /* 1857015Smckusick * If someone's waiting for the buffer, or 1867015Smckusick * is waiting for a buffer wake 'em up. 1877015Smckusick */ 1888Sbill if (bp->b_flags&B_WANTED) 1898Sbill wakeup((caddr_t)bp); 1902325Swnj if (bfreelist[0].b_flags&B_WANTED) { 1912325Swnj bfreelist[0].b_flags &= ~B_WANTED; 1922325Swnj wakeup((caddr_t)bfreelist); 1938Sbill } 1942683Swnj if (bp->b_flags&B_ERROR) 1952683Swnj if (bp->b_flags & B_LOCKED) 1962683Swnj bp->b_flags &= ~B_ERROR; /* try again later */ 1972683Swnj else 1982683Swnj bp->b_dev = NODEV; /* no assoc */ 1997015Smckusick 2007015Smckusick /* 2017015Smckusick * Stick the buffer back on a free list. 2027015Smckusick */ 20326271Skarels s = splbio(); 2048670S if (bp->b_bufsize <= 0) { 2058670S /* block has no buffer ... put at front of unused buffer list */ 2068670S flist = &bfreelist[BQ_EMPTY]; 2078670S binsheadfree(bp, flist); 2088670S } else if (bp->b_flags & (B_ERROR|B_INVAL)) { 2092325Swnj /* block has no info ... put at front of most free list */ 2108670S flist = &bfreelist[BQ_AGE]; 2117015Smckusick binsheadfree(bp, flist); 2128Sbill } else { 2132325Swnj if (bp->b_flags & B_LOCKED) 2142325Swnj flist = &bfreelist[BQ_LOCKED]; 2152325Swnj else if (bp->b_flags & B_AGE) 2162325Swnj flist = &bfreelist[BQ_AGE]; 2172325Swnj else 2182325Swnj flist = &bfreelist[BQ_LRU]; 2197015Smckusick binstailfree(bp, flist); 2208Sbill } 2218Sbill bp->b_flags &= ~(B_WANTED|B_BUSY|B_ASYNC|B_AGE); 2228Sbill splx(s); 2238Sbill } 2248Sbill 2258Sbill /* 2268Sbill * See if the block is associated with some buffer 2278Sbill * (mainly to avoid getting hung up on a wait in breada) 2288Sbill */ 2298Sbill incore(dev, blkno) 2307015Smckusick dev_t dev; 2317015Smckusick daddr_t blkno; 2328Sbill { 2338Sbill register struct buf *bp; 2342325Swnj register struct buf *dp; 2358Sbill 2366563Smckusic dp = BUFHASH(dev, blkno); 2372325Swnj for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) 2386563Smckusic if (bp->b_blkno == blkno && bp->b_dev == dev && 2397015Smckusick (bp->b_flags & B_INVAL) == 0) 24091Sbill return (1); 24191Sbill return (0); 2428Sbill } 2438Sbill 2448Sbill struct buf * 2456563Smckusic baddr(dev, blkno, size) 2466563Smckusic dev_t dev; 2476563Smckusic daddr_t blkno; 2486563Smckusic int size; 2498Sbill { 2508Sbill 2518Sbill if (incore(dev, blkno)) 2526563Smckusic return (bread(dev, blkno, size)); 2538Sbill return (0); 2548Sbill } 2558Sbill 2568Sbill /* 2578Sbill * Assign a buffer for the given block. If the appropriate 2588Sbill * block is already associated, return it; otherwise search 2598Sbill * for the oldest non-busy buffer and reassign it. 2605424Swnj * 261*32608Smckusick * If we find the buffer, but it is dirty (marked DELWRI) and 262*32608Smckusick * its size is changing, we must write it out first. When the 263*32608Smckusick * buffer is shrinking, the write is done by brealloc to avoid 264*32608Smckusick * losing the unwritten data. When the buffer is growing, the 265*32608Smckusick * write is done by getblk, so that bread will not read stale 266*32608Smckusick * disk data over the modified data in the buffer. 267*32608Smckusick * 2685424Swnj * We use splx here because this routine may be called 2695424Swnj * on the interrupt stack during a dump, and we don't 2705424Swnj * want to lower the ipl back to 0. 2718Sbill */ 2728Sbill struct buf * 2736563Smckusic getblk(dev, blkno, size) 2746563Smckusic dev_t dev; 2756563Smckusic daddr_t blkno; 2766563Smckusic int size; 2778Sbill { 2788670S register struct buf *bp, *dp; 2795424Swnj int s; 2808Sbill 28125255Smckusick if (size > MAXBSIZE) 28225255Smckusick panic("getblk: size too big"); 2837015Smckusick /* 28424730Smckusick * To prevent overflow of 32-bit ints when converting block 28524730Smckusick * numbers to byte offsets, blknos > 2^32 / DEV_BSIZE are set 28624730Smckusick * to the maximum number that can be converted to a byte offset 28724730Smckusick * without overflow. This is historic code; what bug it fixed, 28824730Smckusick * or whether it is still a reasonable thing to do is open to 28924730Smckusick * dispute. mkm 9/85 29024730Smckusick */ 29124730Smckusick if ((unsigned)blkno >= 1 << (sizeof(int)*NBBY-DEV_BSHIFT)) 29224730Smckusick blkno = 1 << ((sizeof(int)*NBBY-DEV_BSHIFT) + 1); 29324730Smckusick /* 2947015Smckusick * Search the cache for the block. If we hit, but 2957015Smckusick * the buffer is in use for i/o, then we wait until 2967015Smckusick * the i/o has completed. 2977015Smckusick */ 2986563Smckusic dp = BUFHASH(dev, blkno); 2997015Smckusick loop: 3002325Swnj for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) { 3016563Smckusic if (bp->b_blkno != blkno || bp->b_dev != dev || 3022325Swnj bp->b_flags&B_INVAL) 3038Sbill continue; 30426271Skarels s = splbio(); 3058Sbill if (bp->b_flags&B_BUSY) { 3068Sbill bp->b_flags |= B_WANTED; 3078Sbill sleep((caddr_t)bp, PRIBIO+1); 3085424Swnj splx(s); 3098Sbill goto loop; 3108Sbill } 3115424Swnj splx(s); 3128Sbill notavail(bp); 313*32608Smckusick if (bp->b_bcount != size) { 314*32608Smckusick if (bp->b_bcount < size && (bp->b_flags&B_DELWRI)) { 315*32608Smckusick bp->b_flags &= ~B_ASYNC; 316*32608Smckusick bwrite(bp); 317*32608Smckusick goto loop; 318*32608Smckusick } 319*32608Smckusick if (brealloc(bp, size) == 0) 320*32608Smckusick goto loop; 321*32608Smckusick } 32216855Smckusick if (bp->b_bcount != size && brealloc(bp, size) == 0) 3237188Sroot goto loop; 3248Sbill bp->b_flags |= B_CACHE; 32526271Skarels return (bp); 3268Sbill } 32791Sbill if (major(dev) >= nblkdev) 32891Sbill panic("blkdev"); 3298670S bp = getnewbuf(); 3306563Smckusic bfree(bp); 3317015Smckusick bremhash(bp); 3327015Smckusick binshash(bp, dp); 3338Sbill bp->b_dev = dev; 3346563Smckusic bp->b_blkno = blkno; 3358670S bp->b_error = 0; 3367188Sroot if (brealloc(bp, size) == 0) 3377188Sroot goto loop; 33826271Skarels return (bp); 3398Sbill } 3408Sbill 3418Sbill /* 3428Sbill * get an empty block, 3438Sbill * not assigned to any particular device 3448Sbill */ 3458Sbill struct buf * 3466563Smckusic geteblk(size) 3476563Smckusic int size; 3488Sbill { 3498670S register struct buf *bp, *flist; 3508Sbill 35125255Smckusick if (size > MAXBSIZE) 35225255Smckusick panic("geteblk: size too big"); 3538Sbill loop: 3548670S bp = getnewbuf(); 3558670S bp->b_flags |= B_INVAL; 3567015Smckusick bfree(bp); 3577015Smckusick bremhash(bp); 3588670S flist = &bfreelist[BQ_AGE]; 3598670S binshash(bp, flist); 3608Sbill bp->b_dev = (dev_t)NODEV; 3618670S bp->b_error = 0; 3627188Sroot if (brealloc(bp, size) == 0) 3637188Sroot goto loop; 36426271Skarels return (bp); 3658Sbill } 3668Sbill 3678Sbill /* 3686563Smckusic * Allocate space associated with a buffer. 3699763Ssam * If can't get space, buffer is released 3706563Smckusic */ 3716563Smckusic brealloc(bp, size) 3726563Smckusic register struct buf *bp; 3736563Smckusic int size; 3746563Smckusic { 3756563Smckusic daddr_t start, last; 3766563Smckusic register struct buf *ep; 3776563Smckusic struct buf *dp; 3786563Smckusic int s; 3796563Smckusic 3806563Smckusic /* 38130749Skarels * First need to make sure that all overlapping previous I/O 3826563Smckusic * is dispatched with. 3836563Smckusic */ 3846563Smckusic if (size == bp->b_bcount) 3857188Sroot return (1); 3867188Sroot if (size < bp->b_bcount) { 3877188Sroot if (bp->b_flags & B_DELWRI) { 3887188Sroot bwrite(bp); 3897188Sroot return (0); 3907188Sroot } 3917188Sroot if (bp->b_flags & B_LOCKED) 3927188Sroot panic("brealloc"); 3939763Ssam return (allocbuf(bp, size)); 3947188Sroot } 3957188Sroot bp->b_flags &= ~B_DONE; 3969763Ssam if (bp->b_dev == NODEV) 3979763Ssam return (allocbuf(bp, size)); 3987016Smckusick 39915795Ssam trace(TR_BREALLOC, pack(bp->b_dev, size), bp->b_blkno); 4007188Sroot /* 4017188Sroot * Search cache for any buffers that overlap the one that we 4027188Sroot * are trying to allocate. Overlapping buffers must be marked 4037188Sroot * invalid, after being written out if they are dirty. (indicated 4047188Sroot * by B_DELWRI) A disk block must be mapped by at most one buffer 4057188Sroot * at any point in time. Care must be taken to avoid deadlocking 4067188Sroot * when two buffer are trying to get the same set of disk blocks. 4077188Sroot */ 4087188Sroot start = bp->b_blkno; 40912644Ssam last = start + btodb(size) - 1; 4106563Smckusic dp = BUFHASH(bp->b_dev, bp->b_blkno); 4116563Smckusic loop: 4126563Smckusic for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) { 4137188Sroot if (ep == bp || ep->b_dev != bp->b_dev || (ep->b_flags&B_INVAL)) 4146563Smckusic continue; 4157188Sroot /* look for overlap */ 4167188Sroot if (ep->b_bcount == 0 || ep->b_blkno > last || 41712644Ssam ep->b_blkno + btodb(ep->b_bcount) <= start) 4187188Sroot continue; 41926271Skarels s = splbio(); 4206563Smckusic if (ep->b_flags&B_BUSY) { 4216563Smckusic ep->b_flags |= B_WANTED; 4226563Smckusic sleep((caddr_t)ep, PRIBIO+1); 4238670S splx(s); 4246563Smckusic goto loop; 4256563Smckusic } 4268670S splx(s); 4277188Sroot notavail(ep); 4286563Smckusic if (ep->b_flags & B_DELWRI) { 4296563Smckusic bwrite(ep); 4306563Smckusic goto loop; 4316563Smckusic } 4327188Sroot ep->b_flags |= B_INVAL; 4337188Sroot brelse(ep); 4346563Smckusic } 4359763Ssam return (allocbuf(bp, size)); 4368670S } 4378670S 4388670S /* 4398670S * Find a buffer which is available for use. 4408670S * Select something from a free list. 4418670S * Preference is to AGE list, then LRU list. 4428670S */ 4438670S struct buf * 4448670S getnewbuf() 4458670S { 4468670S register struct buf *bp, *dp; 4478670S int s; 4488670S 4498670S loop: 45026271Skarels s = splbio(); 4518670S for (dp = &bfreelist[BQ_AGE]; dp > bfreelist; dp--) 4528670S if (dp->av_forw != dp) 4538670S break; 4548670S if (dp == bfreelist) { /* no free blocks */ 4558670S dp->b_flags |= B_WANTED; 4568670S sleep((caddr_t)dp, PRIBIO+1); 45712170Ssam splx(s); 4588670S goto loop; 4598670S } 4608670S splx(s); 4618670S bp = dp->av_forw; 4628670S notavail(bp); 4638670S if (bp->b_flags & B_DELWRI) { 4648670S bp->b_flags |= B_ASYNC; 4658670S bwrite(bp); 4668670S goto loop; 4678670S } 46815795Ssam trace(TR_BRELSE, pack(bp->b_dev, bp->b_bufsize), bp->b_blkno); 4698670S bp->b_flags = B_BUSY; 4708670S return (bp); 4718670S } 4728670S 4738670S /* 4748Sbill * Wait for I/O completion on the buffer; return errors 4758Sbill * to the user. 4768Sbill */ 4777015Smckusick biowait(bp) 4786563Smckusic register struct buf *bp; 4798Sbill { 4805431Sroot int s; 4818Sbill 48226271Skarels s = splbio(); 4838Sbill while ((bp->b_flags&B_DONE)==0) 4848Sbill sleep((caddr_t)bp, PRIBIO); 4855431Sroot splx(s); 48611841Ssam if (u.u_error == 0) /* XXX */ 48711841Ssam u.u_error = geterror(bp); 4888Sbill } 4898Sbill 4908Sbill /* 49113128Ssam * Mark I/O complete on a buffer. 49213128Ssam * If someone should be called, e.g. the pageout 49313128Ssam * daemon, do so. Otherwise, wake up anyone 49413128Ssam * waiting for it. 4958Sbill */ 4967015Smckusick biodone(bp) 4977015Smckusick register struct buf *bp; 4988Sbill { 4998Sbill 500420Sbill if (bp->b_flags & B_DONE) 5017015Smckusick panic("dup biodone"); 5028Sbill bp->b_flags |= B_DONE; 5039763Ssam if (bp->b_flags & B_CALL) { 5049763Ssam bp->b_flags &= ~B_CALL; 5059763Ssam (*bp->b_iodone)(bp); 5069763Ssam return; 5079763Ssam } 5088Sbill if (bp->b_flags&B_ASYNC) 5098Sbill brelse(bp); 5108Sbill else { 5118Sbill bp->b_flags &= ~B_WANTED; 5128Sbill wakeup((caddr_t)bp); 5138Sbill } 5148Sbill } 5158Sbill 5168Sbill /* 5178670S * Insure that no part of a specified block is in an incore buffer. 51830749Skarels #ifdef SECSIZE 51930749Skarels * "size" is given in device blocks (the units of b_blkno). 52030749Skarels #endif SECSIZE 5218670S */ 5228670S blkflush(dev, blkno, size) 5238670S dev_t dev; 5248670S daddr_t blkno; 5258670S long size; 5268670S { 5278670S register struct buf *ep; 5288670S struct buf *dp; 5298670S daddr_t start, last; 5308670S int s; 5318670S 5328670S start = blkno; 53312644Ssam last = start + btodb(size) - 1; 5348670S dp = BUFHASH(dev, blkno); 5358670S loop: 5368670S for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) { 5378670S if (ep->b_dev != dev || (ep->b_flags&B_INVAL)) 5388670S continue; 5398670S /* look for overlap */ 5408670S if (ep->b_bcount == 0 || ep->b_blkno > last || 54112644Ssam ep->b_blkno + btodb(ep->b_bcount) <= start) 5428670S continue; 54326271Skarels s = splbio(); 5448670S if (ep->b_flags&B_BUSY) { 5458670S ep->b_flags |= B_WANTED; 5468670S sleep((caddr_t)ep, PRIBIO+1); 5478670S splx(s); 5488670S goto loop; 5498670S } 5508670S if (ep->b_flags & B_DELWRI) { 5518670S splx(s); 5528670S notavail(ep); 5538670S bwrite(ep); 5548670S goto loop; 5558670S } 5568670S splx(s); 5578670S } 5588670S } 5598670S 5608670S /* 56113128Ssam * Make sure all write-behind blocks 5628Sbill * on dev (or NODEV for all) 5638Sbill * are flushed out. 5648Sbill * (from umount and update) 5658Sbill */ 5668Sbill bflush(dev) 5677015Smckusick dev_t dev; 5688Sbill { 5698Sbill register struct buf *bp; 5702325Swnj register struct buf *flist; 5715431Sroot int s; 5728Sbill 5738Sbill loop: 57426271Skarels s = splbio(); 5758670S for (flist = bfreelist; flist < &bfreelist[BQ_EMPTY]; flist++) 5762325Swnj for (bp = flist->av_forw; bp != flist; bp = bp->av_forw) { 5777015Smckusick if ((bp->b_flags & B_DELWRI) == 0) 5787015Smckusick continue; 5797015Smckusick if (dev == NODEV || dev == bp->b_dev) { 5808Sbill bp->b_flags |= B_ASYNC; 5818Sbill notavail(bp); 5828Sbill bwrite(bp); 58312173Ssam splx(s); 5848Sbill goto loop; 5858Sbill } 5868Sbill } 5875431Sroot splx(s); 5888Sbill } 5898Sbill 5908Sbill /* 5918Sbill * Pick up the device's error number and pass it to the user; 59224829Skarels * if there is an error but the number is 0 set a generalized code. 5938Sbill */ 5948Sbill geterror(bp) 5957015Smckusick register struct buf *bp; 5968Sbill { 5977723Swnj int error = 0; 5988Sbill 5998Sbill if (bp->b_flags&B_ERROR) 6007723Swnj if ((error = bp->b_error)==0) 6017723Swnj return (EIO); 6027723Swnj return (error); 6038Sbill } 6042299Skre 6052299Skre /* 6062299Skre * Invalidate in core blocks belonging to closed or umounted filesystem 6072299Skre * 6082299Skre * This is not nicely done at all - the buffer ought to be removed from the 6092299Skre * hash chains & have its dev/blkno fields clobbered, but unfortunately we 6102299Skre * can't do that here, as it is quite possible that the block is still 6112299Skre * being used for i/o. Eventually, all disc drivers should be forced to 6122299Skre * have a close routine, which ought ensure that the queue is empty, then 6132299Skre * properly flush the queues. Until that happy day, this suffices for 6142299Skre * correctness. ... kre 6152299Skre */ 6162299Skre binval(dev) 6177015Smckusick dev_t dev; 6182299Skre { 6192361Skre register struct buf *bp; 6202361Skre register struct bufhd *hp; 6212361Skre #define dp ((struct buf *)hp) 6222299Skre 6232361Skre for (hp = bufhash; hp < &bufhash[BUFHSZ]; hp++) 6242361Skre for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) 6252361Skre if (bp->b_dev == dev) 6262361Skre bp->b_flags |= B_INVAL; 6272299Skre } 628