123395Smckusick /* 237736Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337736Smckusick * All rights reserved. 423395Smckusick * 544454Sbostic * %sccs.include.redist.c% 637736Smckusick * 7*46989Smckusick * @(#)vfs_cluster.c 7.33 (Berkeley) 03/04/91 823395Smckusick */ 98Sbill 1017098Sbloom #include "param.h" 1117098Sbloom #include "user.h" 1217098Sbloom #include "buf.h" 1337736Smckusick #include "vnode.h" 1440652Smckusick #include "specdev.h" 1539668Smckusick #include "mount.h" 1617098Sbloom #include "trace.h" 1738776Smckusick #include "ucred.h" 188Sbill 1991Sbill /* 2046151Smckusick * Find the block in the buffer pool. 2146151Smckusick * If the buffer is not present, allocate a new buffer and load 2246151Smckusick * its contents according to the filesystem fill routine. 238Sbill */ 2438776Smckusick bread(vp, blkno, size, cred, bpp) 2537736Smckusick struct vnode *vp; 266563Smckusic daddr_t blkno; 276563Smckusic int size; 2838776Smckusick struct ucred *cred; 2937736Smckusick struct buf **bpp; 308Sbill { 318Sbill register struct buf *bp; 328Sbill 338670S if (size == 0) 348670S panic("bread: size 0"); 3537736Smckusick *bpp = bp = getblk(vp, blkno, size); 3646151Smckusick if (bp->b_flags & (B_DONE | B_DELWRI)) { 3740341Smckusick trace(TR_BREADHIT, pack(vp, size), blkno); 3837736Smckusick return (0); 398Sbill } 408Sbill bp->b_flags |= B_READ; 418670S if (bp->b_bcount > bp->b_bufsize) 428670S panic("bread"); 4338776Smckusick if (bp->b_rcred == NOCRED && cred != NOCRED) { 4438776Smckusick crhold(cred); 4538776Smckusick bp->b_rcred = cred; 4638776Smckusick } 4737736Smckusick VOP_STRATEGY(bp); 4840341Smckusick trace(TR_BREADMISS, pack(vp, size), blkno); 498039Sroot u.u_ru.ru_inblock++; /* pay for read */ 5037736Smckusick return (biowait(bp)); 518Sbill } 528Sbill 538Sbill /* 5446151Smckusick * Operates like bread, but also starts I/O on the specified 5546151Smckusick * read-ahead block. 568Sbill */ 5738776Smckusick breada(vp, blkno, size, rablkno, rabsize, cred, bpp) 5837736Smckusick struct vnode *vp; 597114Smckusick daddr_t blkno; int size; 608592Sroot daddr_t rablkno; int rabsize; 6138776Smckusick struct ucred *cred; 6237736Smckusick struct buf **bpp; 638Sbill { 648Sbill register struct buf *bp, *rabp; 658Sbill 668Sbill bp = NULL; 677015Smckusick /* 6846151Smckusick * If the block is not memory resident, 6946151Smckusick * allocate a buffer and start I/O. 707015Smckusick */ 7137736Smckusick if (!incore(vp, blkno)) { 7237736Smckusick *bpp = bp = getblk(vp, blkno, size); 7346151Smckusick 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"); 7738776Smckusick if (bp->b_rcred == NOCRED && cred != NOCRED) { 7838776Smckusick crhold(cred); 7938776Smckusick bp->b_rcred = cred; 8038776Smckusick } 8137736Smckusick VOP_STRATEGY(bp); 8240341Smckusick trace(TR_BREADMISS, pack(vp, size), blkno); 838039Sroot u.u_ru.ru_inblock++; /* pay for read */ 847015Smckusick } else 8540341Smckusick trace(TR_BREADHIT, pack(vp, size), blkno); 868Sbill } 877015Smckusick 887015Smckusick /* 8946151Smckusick * If there is a read-ahead block, start I/O on it too. 907015Smckusick */ 9139895Smckusick if (!incore(vp, rablkno)) { 9237736Smckusick rabp = getblk(vp, rablkno, rabsize); 9346151Smckusick if (rabp->b_flags & (B_DONE | B_DELWRI)) { 948Sbill brelse(rabp); 9540341Smckusick trace(TR_BREADHITRA, pack(vp, rabsize), rablkno); 962045Swnj } else { 9746151Smckusick rabp->b_flags |= B_ASYNC | B_READ; 988670S if (rabp->b_bcount > rabp->b_bufsize) 998670S panic("breadrabp"); 10038880Smckusick if (rabp->b_rcred == NOCRED && cred != NOCRED) { 10138776Smckusick crhold(cred); 10238880Smckusick rabp->b_rcred = cred; 10338776Smckusick } 10437736Smckusick VOP_STRATEGY(rabp); 10540341Smckusick trace(TR_BREADMISSRA, pack(vp, rabsize), rablkno); 1068039Sroot u.u_ru.ru_inblock++; /* pay in advance */ 1078Sbill } 1088Sbill } 1097015Smckusick 1107015Smckusick /* 11146151Smckusick * If block was memory resident, let bread get it. 11246151Smckusick * If block was not memory resident, the read was 11346151Smckusick * started above, so just wait for the read to complete. 1147015Smckusick */ 1157114Smckusick if (bp == NULL) 11638776Smckusick return (bread(vp, blkno, size, cred, bpp)); 11737736Smckusick return (biowait(bp)); 1188Sbill } 1198Sbill 1208Sbill /* 12146151Smckusick * Synchronous write. 12246151Smckusick * Release buffer on completion. 1238Sbill */ 1248Sbill bwrite(bp) 1257015Smckusick register struct buf *bp; 1268Sbill { 12737736Smckusick register int flag; 12840226Smckusick int s, error; 1298Sbill 1308Sbill flag = bp->b_flags; 1319857Ssam bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI); 13246151Smckusick if ((flag & B_DELWRI) == 0) 1338039Sroot u.u_ru.ru_oublock++; /* noone paid yet */ 13439882Smckusick else 13539882Smckusick reassignbuf(bp, bp->b_vp); 13640341Smckusick trace(TR_BWRITE, pack(bp->b_vp, bp->b_bcount), bp->b_lblkno); 1378670S if (bp->b_bcount > bp->b_bufsize) 1388670S panic("bwrite"); 13940226Smckusick s = splbio(); 14039882Smckusick bp->b_vp->v_numoutput++; 14140226Smckusick splx(s); 14237736Smckusick VOP_STRATEGY(bp); 1437015Smckusick 1447015Smckusick /* 14546151Smckusick * If the write was synchronous, then await I/O completion. 1467015Smckusick * If the write was "delayed", then we put the buffer on 14746151Smckusick * the queue of blocks awaiting I/O completion status. 1487015Smckusick */ 14946151Smckusick if ((flag & B_ASYNC) == 0) { 15037736Smckusick error = biowait(bp); 1518Sbill brelse(bp); 15237736Smckusick } else if (flag & B_DELWRI) { 1538Sbill bp->b_flags |= B_AGE; 15437736Smckusick error = 0; 15537736Smckusick } 15637736Smckusick return (error); 1578Sbill } 1588Sbill 1598Sbill /* 16046151Smckusick * Delayed write. 16146151Smckusick * 16246151Smckusick * The buffer is marked dirty, but is not queued for I/O. 16346151Smckusick * This routine should be used when the buffer is expected 16446151Smckusick * to be modified again soon, typically a small write that 16546151Smckusick * partially fills a buffer. 16646151Smckusick * 16746151Smckusick * NB: magnetic tapes cannot be delayed; they must be 16846151Smckusick * written in the order that the writes are requested. 1698Sbill */ 1708Sbill bdwrite(bp) 1717015Smckusick register struct buf *bp; 1728Sbill { 1738Sbill 17439882Smckusick if ((bp->b_flags & B_DELWRI) == 0) { 17539882Smckusick bp->b_flags |= B_DELWRI; 17639882Smckusick reassignbuf(bp, bp->b_vp); 1778039Sroot u.u_ru.ru_oublock++; /* noone paid yet */ 17839882Smckusick } 17937736Smckusick /* 18039668Smckusick * If this is a tape drive, the write must be initiated. 18137736Smckusick */ 18239668Smckusick if (VOP_IOCTL(bp->b_vp, 0, B_TAPE, 0, NOCRED) == 0) { 1838Sbill bawrite(bp); 18439668Smckusick } else { 18546151Smckusick bp->b_flags |= (B_DONE | B_DELWRI); 1868Sbill brelse(bp); 1878Sbill } 1888Sbill } 1898Sbill 1908Sbill /* 19146151Smckusick * Asynchronous write. 19246151Smckusick * Start I/O on a buffer, but do not wait for it to complete. 19346151Smckusick * The buffer is released when the I/O completes. 1948Sbill */ 1958Sbill bawrite(bp) 1967015Smckusick register struct buf *bp; 1978Sbill { 1988Sbill 19946151Smckusick /* 20046151Smckusick * Setting the ASYNC flag causes bwrite to return 20146151Smckusick * after starting the I/O. 20246151Smckusick */ 2038Sbill bp->b_flags |= B_ASYNC; 20437736Smckusick (void) bwrite(bp); 2058Sbill } 2068Sbill 2078Sbill /* 20846151Smckusick * Release a buffer. 20946151Smckusick * Even if the buffer is dirty, no I/O is started. 2108Sbill */ 2118Sbill brelse(bp) 2127015Smckusick register struct buf *bp; 2138Sbill { 2142325Swnj register struct buf *flist; 21546151Smckusick int s; 2168Sbill 21740341Smckusick trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno); 2187015Smckusick /* 21939668Smckusick * If a process is waiting for the buffer, or 22039668Smckusick * is waiting for a free buffer, awaken it. 2217015Smckusick */ 22246151Smckusick if (bp->b_flags & B_WANTED) 2238Sbill wakeup((caddr_t)bp); 22446151Smckusick if (bfreelist[0].b_flags & B_WANTED) { 2252325Swnj bfreelist[0].b_flags &= ~B_WANTED; 2262325Swnj wakeup((caddr_t)bfreelist); 2278Sbill } 22839668Smckusick /* 22939668Smckusick * Retry I/O for locked buffers rather than invalidating them. 23039668Smckusick */ 23139668Smckusick if ((bp->b_flags & B_ERROR) && (bp->b_flags & B_LOCKED)) 23239668Smckusick bp->b_flags &= ~B_ERROR; 23339668Smckusick /* 23439668Smckusick * Disassociate buffers that are no longer valid. 23539668Smckusick */ 23646151Smckusick if (bp->b_flags & (B_NOCACHE | B_ERROR)) 23737736Smckusick bp->b_flags |= B_INVAL; 23846151Smckusick if ((bp->b_bufsize <= 0) || (bp->b_flags & (B_ERROR | B_INVAL))) { 23939668Smckusick if (bp->b_vp) 24039668Smckusick brelvp(bp); 24139668Smckusick bp->b_flags &= ~B_DELWRI; 24237736Smckusick } 2437015Smckusick /* 2447015Smckusick * Stick the buffer back on a free list. 2457015Smckusick */ 24626271Skarels s = splbio(); 2478670S if (bp->b_bufsize <= 0) { 2488670S /* block has no buffer ... put at front of unused buffer list */ 2498670S flist = &bfreelist[BQ_EMPTY]; 2508670S binsheadfree(bp, flist); 25146151Smckusick } else if (bp->b_flags & (B_ERROR | B_INVAL)) { 2522325Swnj /* block has no info ... put at front of most free list */ 2538670S flist = &bfreelist[BQ_AGE]; 2547015Smckusick binsheadfree(bp, flist); 2558Sbill } else { 2562325Swnj if (bp->b_flags & B_LOCKED) 2572325Swnj flist = &bfreelist[BQ_LOCKED]; 2582325Swnj else if (bp->b_flags & B_AGE) 2592325Swnj flist = &bfreelist[BQ_AGE]; 2602325Swnj else 2612325Swnj flist = &bfreelist[BQ_LRU]; 2627015Smckusick binstailfree(bp, flist); 2638Sbill } 26446151Smckusick bp->b_flags &= ~(B_WANTED | B_BUSY | B_ASYNC | B_AGE | B_NOCACHE); 2658Sbill splx(s); 2668Sbill } 2678Sbill 2688Sbill /* 26946151Smckusick * Check to see if a block is currently memory resident. 2708Sbill */ 27137736Smckusick incore(vp, blkno) 27237736Smckusick struct vnode *vp; 2737015Smckusick daddr_t blkno; 2748Sbill { 2758Sbill register struct buf *bp; 2762325Swnj register struct buf *dp; 2778Sbill 27838225Smckusick dp = BUFHASH(vp, blkno); 2792325Swnj for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) 28039668Smckusick if (bp->b_lblkno == blkno && bp->b_vp == vp && 2817015Smckusick (bp->b_flags & B_INVAL) == 0) 28291Sbill return (1); 28391Sbill return (0); 2848Sbill } 2858Sbill 28639668Smckusick /* 28746151Smckusick * Check to see if a block is currently memory resident. 28846151Smckusick * If it is resident, return it. If it is not resident, 28946151Smckusick * allocate a new buffer and assign it to the block. 29039668Smckusick */ 2918Sbill struct buf * 29237736Smckusick getblk(vp, blkno, size) 29337736Smckusick register struct vnode *vp; 2946563Smckusic daddr_t blkno; 2956563Smckusic int size; 2968Sbill { 2978670S register struct buf *bp, *dp; 2985424Swnj int s; 2998Sbill 30025255Smckusick if (size > MAXBSIZE) 30125255Smckusick panic("getblk: size too big"); 3027015Smckusick /* 30346151Smckusick * Search the cache for the block. If the buffer is found, 30446151Smckusick * but it is currently locked, the we must wait for it to 30546151Smckusick * become available. 3067015Smckusick */ 30737736Smckusick dp = BUFHASH(vp, blkno); 3087015Smckusick loop: 3092325Swnj for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) { 31039668Smckusick if (bp->b_lblkno != blkno || bp->b_vp != vp || 31146151Smckusick (bp->b_flags & B_INVAL)) 3128Sbill continue; 31326271Skarels s = splbio(); 31446151Smckusick if (bp->b_flags & B_BUSY) { 3158Sbill bp->b_flags |= B_WANTED; 31646151Smckusick sleep((caddr_t)bp, PRIBIO + 1); 3175424Swnj splx(s); 3188Sbill goto loop; 3198Sbill } 32039882Smckusick bremfree(bp); 32139882Smckusick bp->b_flags |= B_BUSY; 3225424Swnj splx(s); 32332608Smckusick if (bp->b_bcount != size) { 32439668Smckusick printf("getblk: stray size"); 32539668Smckusick bp->b_flags |= B_INVAL; 32639668Smckusick bwrite(bp); 32739668Smckusick goto loop; 32832608Smckusick } 3298Sbill bp->b_flags |= B_CACHE; 33026271Skarels return (bp); 3318Sbill } 3328670S bp = getnewbuf(); 3337015Smckusick bremhash(bp); 33439668Smckusick bgetvp(vp, bp); 33545116Smckusick bp->b_bcount = 0; 33639668Smckusick bp->b_lblkno = blkno; 3376563Smckusic bp->b_blkno = blkno; 3388670S bp->b_error = 0; 33937736Smckusick bp->b_resid = 0; 34037736Smckusick binshash(bp, dp); 34145116Smckusick allocbuf(bp, size); 34226271Skarels return (bp); 3438Sbill } 3448Sbill 3458Sbill /* 34646151Smckusick * Allocate a buffer. 34746151Smckusick * The caller will assign it to a block. 3488Sbill */ 3498Sbill struct buf * 3506563Smckusic geteblk(size) 3516563Smckusic int size; 3528Sbill { 3538670S register struct buf *bp, *flist; 3548Sbill 35525255Smckusick if (size > MAXBSIZE) 35625255Smckusick panic("geteblk: size too big"); 3578670S bp = getnewbuf(); 3588670S bp->b_flags |= B_INVAL; 3597015Smckusick bremhash(bp); 3608670S flist = &bfreelist[BQ_AGE]; 36145116Smckusick bp->b_bcount = 0; 36237736Smckusick bp->b_error = 0; 36337736Smckusick bp->b_resid = 0; 3648670S binshash(bp, flist); 36545116Smckusick allocbuf(bp, size); 36626271Skarels return (bp); 3678Sbill } 3688Sbill 3698Sbill /* 37045116Smckusick * Expand or contract the actual memory allocated to a buffer. 37146151Smckusick * If no memory is available, release buffer and take error exit. 3726563Smckusic */ 37345116Smckusick allocbuf(tp, size) 37445116Smckusick register struct buf *tp; 3756563Smckusic int size; 3766563Smckusic { 37745116Smckusick register struct buf *bp, *ep; 37845116Smckusick int sizealloc, take, s; 3796563Smckusic 38045116Smckusick sizealloc = roundup(size, CLBYTES); 38145116Smckusick /* 38245116Smckusick * Buffer size does not change 38345116Smckusick */ 38445116Smckusick if (sizealloc == tp->b_bufsize) 38545116Smckusick goto out; 38645116Smckusick /* 38745116Smckusick * Buffer size is shrinking. 38845116Smckusick * Place excess space in a buffer header taken from the 38945116Smckusick * BQ_EMPTY buffer list and placed on the "most free" list. 39045116Smckusick * If no extra buffer headers are available, leave the 39145116Smckusick * extra space in the present buffer. 39245116Smckusick */ 39345116Smckusick if (sizealloc < tp->b_bufsize) { 39445116Smckusick ep = bfreelist[BQ_EMPTY].av_forw; 39545116Smckusick if (ep == &bfreelist[BQ_EMPTY]) 39645116Smckusick goto out; 39745116Smckusick s = splbio(); 39845116Smckusick bremfree(ep); 39945116Smckusick ep->b_flags |= B_BUSY; 40045116Smckusick splx(s); 40145116Smckusick pagemove(tp->b_un.b_addr + sizealloc, ep->b_un.b_addr, 40245116Smckusick (int)tp->b_bufsize - sizealloc); 40345116Smckusick ep->b_bufsize = tp->b_bufsize - sizealloc; 40445116Smckusick tp->b_bufsize = sizealloc; 40545116Smckusick ep->b_flags |= B_INVAL; 40645116Smckusick ep->b_bcount = 0; 40745116Smckusick brelse(ep); 40845116Smckusick goto out; 40945116Smckusick } 41045116Smckusick /* 41145116Smckusick * More buffer space is needed. Get it out of buffers on 41245116Smckusick * the "most free" list, placing the empty headers on the 41345116Smckusick * BQ_EMPTY buffer header list. 41445116Smckusick */ 41545116Smckusick while (tp->b_bufsize < sizealloc) { 41645116Smckusick take = sizealloc - tp->b_bufsize; 41745116Smckusick bp = getnewbuf(); 41845116Smckusick if (take >= bp->b_bufsize) 41945116Smckusick take = bp->b_bufsize; 42045116Smckusick pagemove(&bp->b_un.b_addr[bp->b_bufsize - take], 42145116Smckusick &tp->b_un.b_addr[tp->b_bufsize], take); 42245116Smckusick tp->b_bufsize += take; 42345116Smckusick bp->b_bufsize = bp->b_bufsize - take; 42445116Smckusick if (bp->b_bcount > bp->b_bufsize) 42545116Smckusick bp->b_bcount = bp->b_bufsize; 42645116Smckusick if (bp->b_bufsize <= 0) { 42745116Smckusick bremhash(bp); 42845116Smckusick binshash(bp, &bfreelist[BQ_EMPTY]); 42946151Smckusick bp->b_dev = NODEV; 43045116Smckusick bp->b_error = 0; 43145116Smckusick bp->b_flags |= B_INVAL; 43245116Smckusick } 43345116Smckusick brelse(bp); 43445116Smckusick } 43545116Smckusick out: 43645116Smckusick tp->b_bcount = size; 43745116Smckusick return (1); 4388670S } 4398670S 4408670S /* 4418670S * Find a buffer which is available for use. 4428670S * Select something from a free list. 4438670S * Preference is to AGE list, then LRU list. 4448670S */ 4458670S struct buf * 4468670S getnewbuf() 4478670S { 4488670S register struct buf *bp, *dp; 44938776Smckusick register struct ucred *cred; 4508670S int s; 4518670S 4528670S loop: 45326271Skarels s = splbio(); 4548670S for (dp = &bfreelist[BQ_AGE]; dp > bfreelist; dp--) 4558670S if (dp->av_forw != dp) 4568670S break; 4578670S if (dp == bfreelist) { /* no free blocks */ 4588670S dp->b_flags |= B_WANTED; 45946151Smckusick sleep((caddr_t)dp, PRIBIO + 1); 46012170Ssam splx(s); 4618670S goto loop; 4628670S } 46339882Smckusick bp = dp->av_forw; 46439882Smckusick bremfree(bp); 46539882Smckusick bp->b_flags |= B_BUSY; 4668670S splx(s); 4678670S if (bp->b_flags & B_DELWRI) { 46838614Smckusick (void) bawrite(bp); 4698670S goto loop; 4708670S } 47140341Smckusick trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno); 47239668Smckusick if (bp->b_vp) 47339668Smckusick brelvp(bp); 47438776Smckusick if (bp->b_rcred != NOCRED) { 47538776Smckusick cred = bp->b_rcred; 47638776Smckusick bp->b_rcred = NOCRED; 47738776Smckusick crfree(cred); 47838776Smckusick } 47938776Smckusick if (bp->b_wcred != NOCRED) { 48038776Smckusick cred = bp->b_wcred; 48138776Smckusick bp->b_wcred = NOCRED; 48238776Smckusick crfree(cred); 48338776Smckusick } 4848670S bp->b_flags = B_BUSY; 485*46989Smckusick bp->b_dirtyoff = bp->b_dirtyend = 0; 4868670S return (bp); 4878670S } 4888670S 4898670S /* 49046151Smckusick * Wait for I/O to complete. 49146151Smckusick * 49246151Smckusick * Extract and return any errors associated with the I/O. 49346151Smckusick * If the error flag is set, but no specific error is 49446151Smckusick * given, return EIO. 4958Sbill */ 4967015Smckusick biowait(bp) 4976563Smckusic register struct buf *bp; 4988Sbill { 4995431Sroot int s; 5008Sbill 50126271Skarels s = splbio(); 50238776Smckusick while ((bp->b_flags & B_DONE) == 0) 5038Sbill sleep((caddr_t)bp, PRIBIO); 5045431Sroot splx(s); 50537736Smckusick if ((bp->b_flags & B_ERROR) == 0) 50637736Smckusick return (0); 50737736Smckusick if (bp->b_error) 50837736Smckusick return (bp->b_error); 50937736Smckusick return (EIO); 5108Sbill } 5118Sbill 5128Sbill /* 51313128Ssam * Mark I/O complete on a buffer. 51446151Smckusick * 51546151Smckusick * If a callback has been requested, e.g. the pageout 51646151Smckusick * daemon, do so. Otherwise, awaken waiting processes. 5178Sbill */ 5187015Smckusick biodone(bp) 5197015Smckusick register struct buf *bp; 5208Sbill { 52139882Smckusick register struct vnode *vp; 5228Sbill 523420Sbill if (bp->b_flags & B_DONE) 5247015Smckusick panic("dup biodone"); 5258Sbill bp->b_flags |= B_DONE; 52639882Smckusick if ((bp->b_flags & B_READ) == 0) { 52738776Smckusick bp->b_dirtyoff = bp->b_dirtyend = 0; 52839882Smckusick if (vp = bp->b_vp) { 52939882Smckusick vp->v_numoutput--; 53039882Smckusick if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) { 53139882Smckusick if (vp->v_numoutput < 0) 53239882Smckusick panic("biodone: neg numoutput"); 53339882Smckusick vp->v_flag &= ~VBWAIT; 53439882Smckusick wakeup((caddr_t)&vp->v_numoutput); 53539882Smckusick } 53639882Smckusick } 53739882Smckusick } 5389763Ssam if (bp->b_flags & B_CALL) { 5399763Ssam bp->b_flags &= ~B_CALL; 5409763Ssam (*bp->b_iodone)(bp); 5419763Ssam return; 5429763Ssam } 54346151Smckusick if (bp->b_flags & B_ASYNC) 5448Sbill brelse(bp); 5458Sbill else { 5468Sbill bp->b_flags &= ~B_WANTED; 5478Sbill wakeup((caddr_t)bp); 5488Sbill } 5498Sbill } 5508Sbill 5518Sbill /* 55237736Smckusick * Make sure all write-behind blocks associated 55338776Smckusick * with mount point are flushed out (from sync). 5548Sbill */ 55539668Smckusick mntflushbuf(mountp, flags) 55638776Smckusick struct mount *mountp; 55739668Smckusick int flags; 5588Sbill { 55939668Smckusick register struct vnode *vp; 56039668Smckusick 56141400Smckusick if ((mountp->mnt_flag & MNT_MPBUSY) == 0) 56241299Smckusick panic("mntflushbuf: not busy"); 56339668Smckusick loop: 56441421Smckusick for (vp = mountp->mnt_mounth; vp; vp = vp->v_mountf) { 56539668Smckusick if (vget(vp)) 56639668Smckusick goto loop; 56739668Smckusick vflushbuf(vp, flags); 56839668Smckusick vput(vp); 56941421Smckusick if (vp->v_mount != mountp) 57041421Smckusick goto loop; 57139668Smckusick } 57239668Smckusick } 57339668Smckusick 57439668Smckusick /* 57539668Smckusick * Flush all dirty buffers associated with a vnode. 57639668Smckusick */ 57739668Smckusick vflushbuf(vp, flags) 57839668Smckusick register struct vnode *vp; 57939668Smckusick int flags; 58039668Smckusick { 5818Sbill register struct buf *bp; 58239668Smckusick struct buf *nbp; 5835431Sroot int s; 5848Sbill 5858Sbill loop: 58626271Skarels s = splbio(); 58739882Smckusick for (bp = vp->v_dirtyblkhd; bp; bp = nbp) { 58839668Smckusick nbp = bp->b_blockf; 58939668Smckusick if ((bp->b_flags & B_BUSY)) 59039668Smckusick continue; 59139668Smckusick if ((bp->b_flags & B_DELWRI) == 0) 59239882Smckusick panic("vflushbuf: not dirty"); 59339882Smckusick bremfree(bp); 59439882Smckusick bp->b_flags |= B_BUSY; 59539668Smckusick splx(s); 59639882Smckusick /* 59739882Smckusick * Wait for I/O associated with indirect blocks to complete, 59839882Smckusick * since there is no way to quickly wait for them below. 59946151Smckusick * NB: This is really specific to ufs, but is done here 60039882Smckusick * as it is easier and quicker. 60139882Smckusick */ 60239882Smckusick if (bp->b_vp == vp || (flags & B_SYNC) == 0) { 60339882Smckusick (void) bawrite(bp); 60440639Smckusick s = splbio(); 60539882Smckusick } else { 60639882Smckusick (void) bwrite(bp); 60739882Smckusick goto loop; 60839882Smckusick } 60939668Smckusick } 61039738Smckusick splx(s); 61139668Smckusick if ((flags & B_SYNC) == 0) 61239668Smckusick return; 61339668Smckusick s = splbio(); 61439882Smckusick while (vp->v_numoutput) { 61539882Smckusick vp->v_flag |= VBWAIT; 61646151Smckusick sleep((caddr_t)&vp->v_numoutput, PRIBIO + 1); 61737736Smckusick } 61839738Smckusick splx(s); 61939882Smckusick if (vp->v_dirtyblkhd) { 62039882Smckusick vprint("vflushbuf: dirty", vp); 62139882Smckusick goto loop; 62239882Smckusick } 6238Sbill } 6242299Skre 6252299Skre /* 6262299Skre * Invalidate in core blocks belonging to closed or umounted filesystem 6272299Skre * 62839668Smckusick * Go through the list of vnodes associated with the file system; 62939668Smckusick * for each vnode invalidate any buffers that it holds. Normally 63039668Smckusick * this routine is preceeded by a bflush call, so that on a quiescent 63139668Smckusick * filesystem there will be no dirty buffers when we are done. Binval 63239668Smckusick * returns the count of dirty buffers when it is finished. 6332299Skre */ 63439668Smckusick mntinvalbuf(mountp) 63538776Smckusick struct mount *mountp; 6362299Skre { 63739668Smckusick register struct vnode *vp; 63839668Smckusick int dirty = 0; 63939668Smckusick 64041400Smckusick if ((mountp->mnt_flag & MNT_MPBUSY) == 0) 64141299Smckusick panic("mntinvalbuf: not busy"); 64239668Smckusick loop: 64341421Smckusick for (vp = mountp->mnt_mounth; vp; vp = vp->v_mountf) { 64439668Smckusick if (vget(vp)) 64539668Smckusick goto loop; 64639668Smckusick dirty += vinvalbuf(vp, 1); 64739668Smckusick vput(vp); 64841421Smckusick if (vp->v_mount != mountp) 64941421Smckusick goto loop; 65039668Smckusick } 65139668Smckusick return (dirty); 65239668Smckusick } 65339668Smckusick 65439668Smckusick /* 65539668Smckusick * Flush out and invalidate all buffers associated with a vnode. 65639668Smckusick * Called with the underlying object locked. 65739668Smckusick */ 65839668Smckusick vinvalbuf(vp, save) 65939668Smckusick register struct vnode *vp; 66039668Smckusick int save; 66139668Smckusick { 6622361Skre register struct buf *bp; 66339882Smckusick struct buf *nbp, *blist; 66438633Smckusick int s, dirty = 0; 6652299Skre 66639882Smckusick for (;;) { 66739882Smckusick if (blist = vp->v_dirtyblkhd) 66839882Smckusick /* void */; 66939882Smckusick else if (blist = vp->v_cleanblkhd) 67039882Smckusick /* void */; 67139882Smckusick else 67239882Smckusick break; 67339882Smckusick for (bp = blist; bp; bp = nbp) { 67439882Smckusick nbp = bp->b_blockf; 67539882Smckusick s = splbio(); 67639882Smckusick if (bp->b_flags & B_BUSY) { 67739882Smckusick bp->b_flags |= B_WANTED; 67846151Smckusick sleep((caddr_t)bp, PRIBIO + 1); 67939882Smckusick splx(s); 68039882Smckusick break; 68139882Smckusick } 68239882Smckusick bremfree(bp); 68339882Smckusick bp->b_flags |= B_BUSY; 68438808Smckusick splx(s); 68539882Smckusick if (save && (bp->b_flags & B_DELWRI)) { 68638614Smckusick dirty++; 68739668Smckusick (void) bwrite(bp); 68839882Smckusick break; 68937736Smckusick } 69040034Smckusick if (bp->b_vp != vp) 69140034Smckusick reassignbuf(bp, bp->b_vp); 69240034Smckusick else 69340034Smckusick bp->b_flags |= B_INVAL; 69439882Smckusick brelse(bp); 69538614Smckusick } 69638614Smckusick } 69739882Smckusick if (vp->v_dirtyblkhd || vp->v_cleanblkhd) 69839668Smckusick panic("vinvalbuf: flush failed"); 69938614Smckusick return (dirty); 7002299Skre } 70137736Smckusick 70239668Smckusick /* 70339668Smckusick * Associate a buffer with a vnode. 70439668Smckusick */ 70539668Smckusick bgetvp(vp, bp) 70639668Smckusick register struct vnode *vp; 70739668Smckusick register struct buf *bp; 70839668Smckusick { 70939668Smckusick 71039668Smckusick if (bp->b_vp) 71139668Smckusick panic("bgetvp: not free"); 71239808Smckusick VHOLD(vp); 71339668Smckusick bp->b_vp = vp; 71439668Smckusick if (vp->v_type == VBLK || vp->v_type == VCHR) 71539668Smckusick bp->b_dev = vp->v_rdev; 71639668Smckusick else 71739668Smckusick bp->b_dev = NODEV; 71839668Smckusick /* 71939668Smckusick * Insert onto list for new vnode. 72039668Smckusick */ 72139882Smckusick if (vp->v_cleanblkhd) { 72239882Smckusick bp->b_blockf = vp->v_cleanblkhd; 72339882Smckusick bp->b_blockb = &vp->v_cleanblkhd; 72439882Smckusick vp->v_cleanblkhd->b_blockb = &bp->b_blockf; 72539882Smckusick vp->v_cleanblkhd = bp; 72639668Smckusick } else { 72739882Smckusick vp->v_cleanblkhd = bp; 72839882Smckusick bp->b_blockb = &vp->v_cleanblkhd; 72939668Smckusick bp->b_blockf = NULL; 73039668Smckusick } 73139668Smckusick } 73239668Smckusick 73339668Smckusick /* 73439668Smckusick * Disassociate a buffer from a vnode. 73539668Smckusick */ 73637736Smckusick brelvp(bp) 73739668Smckusick register struct buf *bp; 73837736Smckusick { 73939668Smckusick struct buf *bq; 74037736Smckusick struct vnode *vp; 74137736Smckusick 74237736Smckusick if (bp->b_vp == (struct vnode *) 0) 74339668Smckusick panic("brelvp: NULL"); 74439668Smckusick /* 74539668Smckusick * Delete from old vnode list, if on one. 74639668Smckusick */ 74739668Smckusick if (bp->b_blockb) { 74839668Smckusick if (bq = bp->b_blockf) 74939668Smckusick bq->b_blockb = bp->b_blockb; 75039668Smckusick *bp->b_blockb = bq; 75139668Smckusick bp->b_blockf = NULL; 75239668Smckusick bp->b_blockb = NULL; 75339668Smckusick } 75437736Smckusick vp = bp->b_vp; 75537736Smckusick bp->b_vp = (struct vnode *) 0; 75639808Smckusick HOLDRELE(vp); 75737736Smckusick } 75839668Smckusick 75939668Smckusick /* 76039668Smckusick * Reassign a buffer from one vnode to another. 76139668Smckusick * Used to assign file specific control information 76239668Smckusick * (indirect blocks) to the vnode to which they belong. 76339668Smckusick */ 76439668Smckusick reassignbuf(bp, newvp) 76539668Smckusick register struct buf *bp; 76639668Smckusick register struct vnode *newvp; 76739668Smckusick { 76839882Smckusick register struct buf *bq, **listheadp; 76939668Smckusick 77039882Smckusick if (newvp == NULL) 77139882Smckusick panic("reassignbuf: NULL"); 77239668Smckusick /* 77339668Smckusick * Delete from old vnode list, if on one. 77439668Smckusick */ 77539668Smckusick if (bp->b_blockb) { 77639668Smckusick if (bq = bp->b_blockf) 77739668Smckusick bq->b_blockb = bp->b_blockb; 77839668Smckusick *bp->b_blockb = bq; 77939668Smckusick } 78039668Smckusick /* 78139882Smckusick * If dirty, put on list of dirty buffers; 78239882Smckusick * otherwise insert onto list of clean buffers. 78339668Smckusick */ 78439882Smckusick if (bp->b_flags & B_DELWRI) 78539882Smckusick listheadp = &newvp->v_dirtyblkhd; 78639882Smckusick else 78739882Smckusick listheadp = &newvp->v_cleanblkhd; 78839882Smckusick if (*listheadp) { 78939882Smckusick bp->b_blockf = *listheadp; 79039882Smckusick bp->b_blockb = listheadp; 79139882Smckusick bp->b_blockf->b_blockb = &bp->b_blockf; 79239882Smckusick *listheadp = bp; 79339668Smckusick } else { 79439882Smckusick *listheadp = bp; 79539882Smckusick bp->b_blockb = listheadp; 79639668Smckusick bp->b_blockf = NULL; 79739668Smckusick } 79839668Smckusick } 799