123395Smckusick /* 237736Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337736Smckusick * All rights reserved. 423395Smckusick * 537736Smckusick * Redistribution and use in source and binary forms are permitted 637736Smckusick * provided that the above copyright notice and this paragraph are 737736Smckusick * duplicated in all such forms and that any documentation, 837736Smckusick * advertising materials, and other materials related to such 937736Smckusick * distribution and use acknowledge that the software was developed 1037736Smckusick * by the University of California, Berkeley. The name of the 1137736Smckusick * University may not be used to endorse or promote products derived 1237736Smckusick * from this software without specific prior written permission. 1337736Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437736Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537736Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637736Smckusick * 17*40034Smckusick * @(#)vfs_cluster.c 7.21 (Berkeley) 02/08/90 1823395Smckusick */ 198Sbill 2017098Sbloom #include "param.h" 2117098Sbloom #include "user.h" 2217098Sbloom #include "buf.h" 2337736Smckusick #include "vnode.h" 2439668Smckusick #include "mount.h" 2517098Sbloom #include "trace.h" 2638776Smckusick #include "ucred.h" 278Sbill 2891Sbill /* 298Sbill * Read in (if necessary) the block and return a buffer pointer. 308Sbill */ 3138776Smckusick bread(vp, blkno, size, cred, bpp) 3237736Smckusick struct vnode *vp; 336563Smckusic daddr_t blkno; 346563Smckusic int size; 3538776Smckusick struct ucred *cred; 3637736Smckusick struct buf **bpp; 378Sbill { 388Sbill register struct buf *bp; 398Sbill 408670S if (size == 0) 418670S panic("bread: size 0"); 4237736Smckusick *bpp = bp = getblk(vp, blkno, size); 4332608Smckusick if (bp->b_flags&(B_DONE|B_DELWRI)) { 4437736Smckusick trace(TR_BREADHIT, pack(vp->v_mount->m_fsid[0], size), blkno); 4537736Smckusick return (0); 468Sbill } 478Sbill bp->b_flags |= B_READ; 488670S if (bp->b_bcount > bp->b_bufsize) 498670S panic("bread"); 5038776Smckusick if (bp->b_rcred == NOCRED && cred != NOCRED) { 5138776Smckusick crhold(cred); 5238776Smckusick bp->b_rcred = cred; 5338776Smckusick } 5437736Smckusick VOP_STRATEGY(bp); 5537736Smckusick trace(TR_BREADMISS, pack(vp->v_mount->m_fsid[0], size), blkno); 568039Sroot u.u_ru.ru_inblock++; /* pay for read */ 5737736Smckusick return (biowait(bp)); 588Sbill } 598Sbill 608Sbill /* 618Sbill * Read in the block, like bread, but also start I/O on the 628Sbill * read-ahead block (which is not allocated to the caller) 638Sbill */ 6438776Smckusick breada(vp, blkno, size, rablkno, rabsize, cred, bpp) 6537736Smckusick struct vnode *vp; 667114Smckusick daddr_t blkno; int size; 678592Sroot daddr_t rablkno; int rabsize; 6838776Smckusick struct ucred *cred; 6937736Smckusick struct buf **bpp; 708Sbill { 718Sbill register struct buf *bp, *rabp; 728Sbill 738Sbill bp = NULL; 747015Smckusick /* 757015Smckusick * If the block isn't in core, then allocate 767015Smckusick * a buffer and initiate i/o (getblk checks 777015Smckusick * for a cache hit). 787015Smckusick */ 7937736Smckusick if (!incore(vp, blkno)) { 8037736Smckusick *bpp = bp = getblk(vp, blkno, size); 8132608Smckusick if ((bp->b_flags&(B_DONE|B_DELWRI)) == 0) { 828Sbill bp->b_flags |= B_READ; 838670S if (bp->b_bcount > bp->b_bufsize) 848670S panic("breada"); 8538776Smckusick if (bp->b_rcred == NOCRED && cred != NOCRED) { 8638776Smckusick crhold(cred); 8738776Smckusick bp->b_rcred = cred; 8838776Smckusick } 8937736Smckusick VOP_STRATEGY(bp); 9037736Smckusick trace(TR_BREADMISS, pack(vp->v_mount->m_fsid[0], size), 9137736Smckusick blkno); 928039Sroot u.u_ru.ru_inblock++; /* pay for read */ 937015Smckusick } else 9437736Smckusick trace(TR_BREADHIT, pack(vp->v_mount->m_fsid[0], size), 9537736Smckusick blkno); 968Sbill } 977015Smckusick 987015Smckusick /* 997015Smckusick * If there's a read-ahead block, start i/o 1007015Smckusick * on it also (as above). 1017015Smckusick */ 10239895Smckusick if (!incore(vp, rablkno)) { 10337736Smckusick rabp = getblk(vp, rablkno, rabsize); 10432608Smckusick if (rabp->b_flags & (B_DONE|B_DELWRI)) { 1058Sbill brelse(rabp); 10637736Smckusick trace(TR_BREADHITRA, 10738880Smckusick pack(vp->v_mount->m_fsid[0], rabsize), rablkno); 1082045Swnj } else { 1098Sbill rabp->b_flags |= B_READ|B_ASYNC; 1108670S if (rabp->b_bcount > rabp->b_bufsize) 1118670S panic("breadrabp"); 11238880Smckusick if (rabp->b_rcred == NOCRED && cred != NOCRED) { 11338776Smckusick crhold(cred); 11438880Smckusick rabp->b_rcred = cred; 11538776Smckusick } 11637736Smckusick VOP_STRATEGY(rabp); 11737736Smckusick trace(TR_BREADMISSRA, 11838880Smckusick pack(vp->v_mount->m_fsid[0], rabsize), rablkno); 1198039Sroot u.u_ru.ru_inblock++; /* pay in advance */ 1208Sbill } 1218Sbill } 1227015Smckusick 1237015Smckusick /* 1247114Smckusick * If block was in core, let bread get it. 1257114Smckusick * If block wasn't in core, then the read was started 1267114Smckusick * above, and just wait for it. 1277015Smckusick */ 1287114Smckusick if (bp == NULL) 12938776Smckusick return (bread(vp, blkno, size, cred, bpp)); 13037736Smckusick return (biowait(bp)); 1318Sbill } 1328Sbill 1338Sbill /* 1348Sbill * Write the buffer, waiting for completion. 1358Sbill * Then release the buffer. 1368Sbill */ 1378Sbill bwrite(bp) 1387015Smckusick register struct buf *bp; 1398Sbill { 14037736Smckusick register int flag; 14137736Smckusick int error; 1428Sbill 1438Sbill flag = bp->b_flags; 1449857Ssam bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI); 1458Sbill if ((flag&B_DELWRI) == 0) 1468039Sroot u.u_ru.ru_oublock++; /* noone paid yet */ 14739882Smckusick else 14839882Smckusick reassignbuf(bp, bp->b_vp); 14937736Smckusick trace(TR_BWRITE, 15039668Smckusick pack(bp->b_vp->v_mount->m_fsid[0], bp->b_bcount), bp->b_lblkno); 1518670S if (bp->b_bcount > bp->b_bufsize) 1528670S panic("bwrite"); 15339882Smckusick bp->b_vp->v_numoutput++; 15437736Smckusick VOP_STRATEGY(bp); 1557015Smckusick 1567015Smckusick /* 1577015Smckusick * If the write was synchronous, then await i/o completion. 1587015Smckusick * If the write was "delayed", then we put the buffer on 1597015Smckusick * the q of blocks awaiting i/o completion status. 1607015Smckusick */ 1618Sbill if ((flag&B_ASYNC) == 0) { 16237736Smckusick error = biowait(bp); 1638Sbill brelse(bp); 16437736Smckusick } else if (flag & B_DELWRI) { 1658Sbill bp->b_flags |= B_AGE; 16637736Smckusick error = 0; 16737736Smckusick } 16837736Smckusick return (error); 1698Sbill } 1708Sbill 1718Sbill /* 1728Sbill * Release the buffer, marking it so that if it is grabbed 1738Sbill * for another purpose it will be written out before being 1748Sbill * given up (e.g. when writing a partial block where it is 1758Sbill * assumed that another write for the same block will soon follow). 1768Sbill * This can't be done for magtape, since writes must be done 1778Sbill * in the same order as requested. 1788Sbill */ 1798Sbill bdwrite(bp) 1807015Smckusick register struct buf *bp; 1818Sbill { 1828Sbill 18339882Smckusick if ((bp->b_flags & B_DELWRI) == 0) { 18439882Smckusick bp->b_flags |= B_DELWRI; 18539882Smckusick reassignbuf(bp, bp->b_vp); 1868039Sroot u.u_ru.ru_oublock++; /* noone paid yet */ 18739882Smckusick } 18837736Smckusick /* 18939668Smckusick * If this is a tape drive, the write must be initiated. 19037736Smckusick */ 19139668Smckusick if (VOP_IOCTL(bp->b_vp, 0, B_TAPE, 0, NOCRED) == 0) { 1928Sbill bawrite(bp); 19339668Smckusick } else { 1948Sbill bp->b_flags |= B_DELWRI | B_DONE; 1958Sbill brelse(bp); 1968Sbill } 1978Sbill } 1988Sbill 1998Sbill /* 2008Sbill * Release the buffer, start I/O on it, but don't wait for completion. 2018Sbill */ 2028Sbill bawrite(bp) 2037015Smckusick register struct buf *bp; 2048Sbill { 2058Sbill 2068Sbill bp->b_flags |= B_ASYNC; 20737736Smckusick (void) bwrite(bp); 2088Sbill } 2098Sbill 2108Sbill /* 2117015Smckusick * Release the buffer, with no I/O implied. 2128Sbill */ 2138Sbill brelse(bp) 2147015Smckusick register struct buf *bp; 2158Sbill { 2162325Swnj register struct buf *flist; 2178Sbill register s; 2188Sbill 21937736Smckusick trace(TR_BRELSE, 22039668Smckusick pack(bp->b_vp->v_mount->m_fsid[0], bp->b_bufsize), bp->b_lblkno); 2217015Smckusick /* 22239668Smckusick * If a process is waiting for the buffer, or 22339668Smckusick * is waiting for a free buffer, awaken it. 2247015Smckusick */ 2258Sbill if (bp->b_flags&B_WANTED) 2268Sbill wakeup((caddr_t)bp); 2272325Swnj if (bfreelist[0].b_flags&B_WANTED) { 2282325Swnj bfreelist[0].b_flags &= ~B_WANTED; 2292325Swnj wakeup((caddr_t)bfreelist); 2308Sbill } 23139668Smckusick /* 23239668Smckusick * Retry I/O for locked buffers rather than invalidating them. 23339668Smckusick */ 23439668Smckusick if ((bp->b_flags & B_ERROR) && (bp->b_flags & B_LOCKED)) 23539668Smckusick bp->b_flags &= ~B_ERROR; 23639668Smckusick 23739668Smckusick /* 23839668Smckusick * Disassociate buffers that are no longer valid. 23939668Smckusick */ 24039668Smckusick if (bp->b_flags & (B_NOCACHE|B_ERROR)) 24137736Smckusick bp->b_flags |= B_INVAL; 24239668Smckusick if ((bp->b_bufsize <= 0) || (bp->b_flags & (B_ERROR|B_INVAL))) { 24339668Smckusick if (bp->b_vp) 24439668Smckusick brelvp(bp); 24539668Smckusick bp->b_flags &= ~B_DELWRI; 24637736Smckusick } 2477015Smckusick /* 2487015Smckusick * Stick the buffer back on a free list. 2497015Smckusick */ 25026271Skarels s = splbio(); 2518670S if (bp->b_bufsize <= 0) { 2528670S /* block has no buffer ... put at front of unused buffer list */ 2538670S flist = &bfreelist[BQ_EMPTY]; 2548670S binsheadfree(bp, flist); 2558670S } else if (bp->b_flags & (B_ERROR|B_INVAL)) { 2562325Swnj /* block has no info ... put at front of most free list */ 2578670S flist = &bfreelist[BQ_AGE]; 2587015Smckusick binsheadfree(bp, flist); 2598Sbill } else { 2602325Swnj if (bp->b_flags & B_LOCKED) 2612325Swnj flist = &bfreelist[BQ_LOCKED]; 2622325Swnj else if (bp->b_flags & B_AGE) 2632325Swnj flist = &bfreelist[BQ_AGE]; 2642325Swnj else 2652325Swnj flist = &bfreelist[BQ_LRU]; 2667015Smckusick binstailfree(bp, flist); 2678Sbill } 26837736Smckusick bp->b_flags &= ~(B_WANTED|B_BUSY|B_ASYNC|B_AGE|B_NOCACHE); 2698Sbill splx(s); 2708Sbill } 2718Sbill 2728Sbill /* 2738Sbill * See if the block is associated with some buffer 2748Sbill * (mainly to avoid getting hung up on a wait in breada) 2758Sbill */ 27637736Smckusick incore(vp, blkno) 27737736Smckusick struct vnode *vp; 2787015Smckusick daddr_t blkno; 2798Sbill { 2808Sbill register struct buf *bp; 2812325Swnj register struct buf *dp; 2828Sbill 28338225Smckusick dp = BUFHASH(vp, blkno); 2842325Swnj for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) 28539668Smckusick if (bp->b_lblkno == blkno && bp->b_vp == vp && 2867015Smckusick (bp->b_flags & B_INVAL) == 0) 28791Sbill return (1); 28891Sbill return (0); 2898Sbill } 2908Sbill 29139668Smckusick /* 29239668Smckusick * Return a block if it is in memory. 29339668Smckusick */ 29438776Smckusick baddr(vp, blkno, size, cred, bpp) 29537736Smckusick struct vnode *vp; 2966563Smckusic daddr_t blkno; 2976563Smckusic int size; 29838776Smckusick struct ucred *cred; 29937736Smckusick struct buf **bpp; 3008Sbill { 3018Sbill 30237736Smckusick if (incore(vp, blkno)) 30338776Smckusick return (bread(vp, blkno, size, cred, bpp)); 30437736Smckusick *bpp = 0; 3058Sbill return (0); 3068Sbill } 3078Sbill 3088Sbill /* 3098Sbill * Assign a buffer for the given block. If the appropriate 3108Sbill * block is already associated, return it; otherwise search 3118Sbill * for the oldest non-busy buffer and reassign it. 3125424Swnj * 3135424Swnj * We use splx here because this routine may be called 3145424Swnj * on the interrupt stack during a dump, and we don't 3155424Swnj * want to lower the ipl back to 0. 3168Sbill */ 3178Sbill struct buf * 31837736Smckusick getblk(vp, blkno, size) 31937736Smckusick register struct vnode *vp; 3206563Smckusic daddr_t blkno; 3216563Smckusic int size; 3228Sbill { 3238670S register struct buf *bp, *dp; 3245424Swnj int s; 3258Sbill 32625255Smckusick if (size > MAXBSIZE) 32725255Smckusick panic("getblk: size too big"); 3287015Smckusick /* 32924730Smckusick * To prevent overflow of 32-bit ints when converting block 33024730Smckusick * numbers to byte offsets, blknos > 2^32 / DEV_BSIZE are set 33124730Smckusick * to the maximum number that can be converted to a byte offset 33224730Smckusick * without overflow. This is historic code; what bug it fixed, 33324730Smckusick * or whether it is still a reasonable thing to do is open to 33424730Smckusick * dispute. mkm 9/85 33539668Smckusick * 33639668Smckusick * Make it a panic to see if it ever really happens. mkm 11/89 33724730Smckusick */ 33839668Smckusick if ((unsigned)blkno >= 1 << (sizeof(int)*NBBY-DEV_BSHIFT)) { 33939668Smckusick panic("getblk: blkno too big"); 34024730Smckusick blkno = 1 << ((sizeof(int)*NBBY-DEV_BSHIFT) + 1); 34139668Smckusick } 34224730Smckusick /* 3437015Smckusick * Search the cache for the block. If we hit, but 3447015Smckusick * the buffer is in use for i/o, then we wait until 3457015Smckusick * the i/o has completed. 3467015Smckusick */ 34737736Smckusick dp = BUFHASH(vp, blkno); 3487015Smckusick loop: 3492325Swnj for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) { 35039668Smckusick if (bp->b_lblkno != blkno || bp->b_vp != vp || 3512325Swnj bp->b_flags&B_INVAL) 3528Sbill continue; 35326271Skarels s = splbio(); 3548Sbill if (bp->b_flags&B_BUSY) { 3558Sbill bp->b_flags |= B_WANTED; 3568Sbill sleep((caddr_t)bp, PRIBIO+1); 3575424Swnj splx(s); 3588Sbill goto loop; 3598Sbill } 36039882Smckusick bremfree(bp); 36139882Smckusick bp->b_flags |= B_BUSY; 3625424Swnj splx(s); 36332608Smckusick if (bp->b_bcount != size) { 36439668Smckusick printf("getblk: stray size"); 36539668Smckusick bp->b_flags |= B_INVAL; 36639668Smckusick bwrite(bp); 36739668Smckusick goto loop; 36832608Smckusick } 3698Sbill bp->b_flags |= B_CACHE; 37026271Skarels return (bp); 3718Sbill } 3728670S bp = getnewbuf(); 3736563Smckusic bfree(bp); 3747015Smckusick bremhash(bp); 37539668Smckusick bgetvp(vp, bp); 37639668Smckusick bp->b_lblkno = blkno; 3776563Smckusic bp->b_blkno = blkno; 3788670S bp->b_error = 0; 37937736Smckusick bp->b_resid = 0; 38037736Smckusick binshash(bp, dp); 38139668Smckusick brealloc(bp, size); 38226271Skarels return (bp); 3838Sbill } 3848Sbill 3858Sbill /* 3868Sbill * get an empty block, 3878Sbill * not assigned to any particular device 3888Sbill */ 3898Sbill struct buf * 3906563Smckusic geteblk(size) 3916563Smckusic int size; 3928Sbill { 3938670S register struct buf *bp, *flist; 3948Sbill 39525255Smckusick if (size > MAXBSIZE) 39625255Smckusick panic("geteblk: size too big"); 3978670S bp = getnewbuf(); 3988670S bp->b_flags |= B_INVAL; 3997015Smckusick bfree(bp); 4007015Smckusick bremhash(bp); 4018670S flist = &bfreelist[BQ_AGE]; 40237736Smckusick bp->b_error = 0; 40337736Smckusick bp->b_resid = 0; 4048670S binshash(bp, flist); 40539668Smckusick brealloc(bp, size); 40626271Skarels return (bp); 4078Sbill } 4088Sbill 4098Sbill /* 4106563Smckusic * Allocate space associated with a buffer. 4116563Smckusic */ 4126563Smckusic brealloc(bp, size) 4136563Smckusic register struct buf *bp; 4146563Smckusic int size; 4156563Smckusic { 4166563Smckusic daddr_t start, last; 4176563Smckusic register struct buf *ep; 4186563Smckusic struct buf *dp; 4196563Smckusic int s; 4206563Smckusic 4216563Smckusic if (size == bp->b_bcount) 42239668Smckusick return; 42339668Smckusick allocbuf(bp, size); 4248670S } 4258670S 4268670S /* 4278670S * Find a buffer which is available for use. 4288670S * Select something from a free list. 4298670S * Preference is to AGE list, then LRU list. 4308670S */ 4318670S struct buf * 4328670S getnewbuf() 4338670S { 4348670S register struct buf *bp, *dp; 43538776Smckusick register struct ucred *cred; 4368670S int s; 4378670S 4388670S loop: 43926271Skarels s = splbio(); 4408670S for (dp = &bfreelist[BQ_AGE]; dp > bfreelist; dp--) 4418670S if (dp->av_forw != dp) 4428670S break; 4438670S if (dp == bfreelist) { /* no free blocks */ 4448670S dp->b_flags |= B_WANTED; 4458670S sleep((caddr_t)dp, PRIBIO+1); 44612170Ssam splx(s); 4478670S goto loop; 4488670S } 44939882Smckusick bp = dp->av_forw; 45039882Smckusick bremfree(bp); 45139882Smckusick bp->b_flags |= B_BUSY; 4528670S splx(s); 4538670S if (bp->b_flags & B_DELWRI) { 45438614Smckusick (void) bawrite(bp); 4558670S goto loop; 4568670S } 45737736Smckusick trace(TR_BRELSE, 45839668Smckusick pack(bp->b_vp->v_mount->m_fsid[0], bp->b_bufsize), bp->b_lblkno); 45939668Smckusick if (bp->b_vp) 46039668Smckusick brelvp(bp); 46138776Smckusick if (bp->b_rcred != NOCRED) { 46238776Smckusick cred = bp->b_rcred; 46338776Smckusick bp->b_rcred = NOCRED; 46438776Smckusick crfree(cred); 46538776Smckusick } 46638776Smckusick if (bp->b_wcred != NOCRED) { 46738776Smckusick cred = bp->b_wcred; 46838776Smckusick bp->b_wcred = NOCRED; 46938776Smckusick crfree(cred); 47038776Smckusick } 4718670S bp->b_flags = B_BUSY; 4728670S return (bp); 4738670S } 4748670S 4758670S /* 4768Sbill * Wait for I/O completion on the buffer; return errors 4778Sbill * to the user. 4788Sbill */ 4797015Smckusick biowait(bp) 4806563Smckusic register struct buf *bp; 4818Sbill { 4825431Sroot int s; 4838Sbill 48426271Skarels s = splbio(); 48538776Smckusick while ((bp->b_flags & B_DONE) == 0) 4868Sbill sleep((caddr_t)bp, PRIBIO); 4875431Sroot splx(s); 48837736Smckusick /* 48937736Smckusick * Pick up the device's error number and pass it to the user; 49037736Smckusick * if there is an error but the number is 0 set a generalized code. 49137736Smckusick */ 49237736Smckusick if ((bp->b_flags & B_ERROR) == 0) 49337736Smckusick return (0); 49437736Smckusick if (bp->b_error) 49537736Smckusick return (bp->b_error); 49637736Smckusick return (EIO); 4978Sbill } 4988Sbill 4998Sbill /* 50013128Ssam * Mark I/O complete on a buffer. 50113128Ssam * If someone should be called, e.g. the pageout 50213128Ssam * daemon, do so. Otherwise, wake up anyone 50313128Ssam * waiting for it. 5048Sbill */ 5057015Smckusick biodone(bp) 5067015Smckusick register struct buf *bp; 5078Sbill { 50839882Smckusick register struct vnode *vp; 5098Sbill 510420Sbill if (bp->b_flags & B_DONE) 5117015Smckusick panic("dup biodone"); 5128Sbill bp->b_flags |= B_DONE; 51339882Smckusick if ((bp->b_flags & B_READ) == 0) { 51438776Smckusick bp->b_dirtyoff = bp->b_dirtyend = 0; 51539882Smckusick if (vp = bp->b_vp) { 51639882Smckusick vp->v_numoutput--; 51739882Smckusick if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) { 51839882Smckusick if (vp->v_numoutput < 0) 51939882Smckusick panic("biodone: neg numoutput"); 52039882Smckusick vp->v_flag &= ~VBWAIT; 52139882Smckusick wakeup((caddr_t)&vp->v_numoutput); 52239882Smckusick } 52339882Smckusick } 52439882Smckusick } 5259763Ssam if (bp->b_flags & B_CALL) { 5269763Ssam bp->b_flags &= ~B_CALL; 5279763Ssam (*bp->b_iodone)(bp); 5289763Ssam return; 5299763Ssam } 5308Sbill if (bp->b_flags&B_ASYNC) 5318Sbill brelse(bp); 5328Sbill else { 5338Sbill bp->b_flags &= ~B_WANTED; 5348Sbill wakeup((caddr_t)bp); 5358Sbill } 5368Sbill } 5378Sbill 5388Sbill /* 53937736Smckusick * Make sure all write-behind blocks associated 54038776Smckusick * with mount point are flushed out (from sync). 5418Sbill */ 54239668Smckusick mntflushbuf(mountp, flags) 54338776Smckusick struct mount *mountp; 54439668Smckusick int flags; 5458Sbill { 54639668Smckusick register struct vnode *vp; 54739764Smckusick struct vnode *nvp; 54839668Smckusick 54939668Smckusick loop: 55039764Smckusick for (vp = mountp->m_mounth; vp; vp = nvp) { 55139764Smckusick nvp = vp->v_mountf; 55239668Smckusick if (vget(vp)) 55339668Smckusick goto loop; 55439668Smckusick vflushbuf(vp, flags); 55539668Smckusick vput(vp); 55639668Smckusick } 55739668Smckusick } 55839668Smckusick 55939668Smckusick /* 56039668Smckusick * Flush all dirty buffers associated with a vnode. 56139668Smckusick */ 56239668Smckusick vflushbuf(vp, flags) 56339668Smckusick register struct vnode *vp; 56439668Smckusick int flags; 56539668Smckusick { 5668Sbill register struct buf *bp; 56739668Smckusick struct buf *nbp; 5685431Sroot int s; 5698Sbill 5708Sbill loop: 57126271Skarels s = splbio(); 57239882Smckusick for (bp = vp->v_dirtyblkhd; bp; bp = nbp) { 57339668Smckusick nbp = bp->b_blockf; 57439668Smckusick if ((bp->b_flags & B_BUSY)) 57539668Smckusick continue; 57639668Smckusick if ((bp->b_flags & B_DELWRI) == 0) 57739882Smckusick panic("vflushbuf: not dirty"); 57839882Smckusick bremfree(bp); 57939882Smckusick bp->b_flags |= B_BUSY; 58039668Smckusick splx(s); 58139882Smckusick /* 58239882Smckusick * Wait for I/O associated with indirect blocks to complete, 58339882Smckusick * since there is no way to quickly wait for them below. 58439882Smckusick * NB - This is really specific to ufs, but is done here 58539882Smckusick * as it is easier and quicker. 58639882Smckusick */ 58739882Smckusick if (bp->b_vp == vp || (flags & B_SYNC) == 0) { 58839882Smckusick (void) bawrite(bp); 58939882Smckusick } else { 59039882Smckusick (void) bwrite(bp); 59139882Smckusick goto loop; 59239882Smckusick } 59339668Smckusick } 59439738Smckusick splx(s); 59539668Smckusick if ((flags & B_SYNC) == 0) 59639668Smckusick return; 59739668Smckusick s = splbio(); 59839882Smckusick while (vp->v_numoutput) { 59939882Smckusick vp->v_flag |= VBWAIT; 60039882Smckusick sleep((caddr_t)&vp->v_numoutput, PRIBIO+1); 60137736Smckusick } 60239738Smckusick splx(s); 60339882Smckusick if (vp->v_dirtyblkhd) { 60439882Smckusick vprint("vflushbuf: dirty", vp); 60539882Smckusick goto loop; 60639882Smckusick } 6078Sbill } 6082299Skre 6092299Skre /* 6102299Skre * Invalidate in core blocks belonging to closed or umounted filesystem 6112299Skre * 61239668Smckusick * Go through the list of vnodes associated with the file system; 61339668Smckusick * for each vnode invalidate any buffers that it holds. Normally 61439668Smckusick * this routine is preceeded by a bflush call, so that on a quiescent 61539668Smckusick * filesystem there will be no dirty buffers when we are done. Binval 61639668Smckusick * returns the count of dirty buffers when it is finished. 6172299Skre */ 61839668Smckusick mntinvalbuf(mountp) 61938776Smckusick struct mount *mountp; 6202299Skre { 62139668Smckusick register struct vnode *vp; 62239764Smckusick struct vnode *nvp; 62339668Smckusick int dirty = 0; 62439668Smckusick 62539668Smckusick loop: 62639764Smckusick for (vp = mountp->m_mounth; vp; vp = nvp) { 62739764Smckusick nvp = vp->v_mountf; 62839668Smckusick if (vget(vp)) 62939668Smckusick goto loop; 63039668Smckusick dirty += vinvalbuf(vp, 1); 63139668Smckusick vput(vp); 63239668Smckusick } 63339668Smckusick return (dirty); 63439668Smckusick } 63539668Smckusick 63639668Smckusick /* 63739668Smckusick * Flush out and invalidate all buffers associated with a vnode. 63839668Smckusick * Called with the underlying object locked. 63939668Smckusick */ 64039668Smckusick vinvalbuf(vp, save) 64139668Smckusick register struct vnode *vp; 64239668Smckusick int save; 64339668Smckusick { 6442361Skre register struct buf *bp; 64539882Smckusick struct buf *nbp, *blist; 64638633Smckusick int s, dirty = 0; 6472299Skre 64839882Smckusick for (;;) { 64939882Smckusick if (blist = vp->v_dirtyblkhd) 65039882Smckusick /* void */; 65139882Smckusick else if (blist = vp->v_cleanblkhd) 65239882Smckusick /* void */; 65339882Smckusick else 65439882Smckusick break; 65539882Smckusick for (bp = blist; bp; bp = nbp) { 65639882Smckusick nbp = bp->b_blockf; 65739882Smckusick s = splbio(); 65839882Smckusick if (bp->b_flags & B_BUSY) { 65939882Smckusick bp->b_flags |= B_WANTED; 66039882Smckusick sleep((caddr_t)bp, PRIBIO+1); 66139882Smckusick splx(s); 66239882Smckusick break; 66339882Smckusick } 66439882Smckusick bremfree(bp); 66539882Smckusick bp->b_flags |= B_BUSY; 66638808Smckusick splx(s); 66739882Smckusick if (save && (bp->b_flags & B_DELWRI)) { 66838614Smckusick dirty++; 66939668Smckusick (void) bwrite(bp); 67039882Smckusick break; 67137736Smckusick } 672*40034Smckusick if (bp->b_vp != vp) 673*40034Smckusick reassignbuf(bp, bp->b_vp); 674*40034Smckusick else 675*40034Smckusick bp->b_flags |= B_INVAL; 67639882Smckusick brelse(bp); 67738614Smckusick } 67838614Smckusick } 67939882Smckusick if (vp->v_dirtyblkhd || vp->v_cleanblkhd) 68039668Smckusick panic("vinvalbuf: flush failed"); 68138614Smckusick return (dirty); 6822299Skre } 68337736Smckusick 68439668Smckusick /* 68539668Smckusick * Associate a buffer with a vnode. 68639668Smckusick */ 68739668Smckusick bgetvp(vp, bp) 68839668Smckusick register struct vnode *vp; 68939668Smckusick register struct buf *bp; 69039668Smckusick { 69139668Smckusick 69239668Smckusick if (bp->b_vp) 69339668Smckusick panic("bgetvp: not free"); 69439808Smckusick VHOLD(vp); 69539668Smckusick bp->b_vp = vp; 69639668Smckusick if (vp->v_type == VBLK || vp->v_type == VCHR) 69739668Smckusick bp->b_dev = vp->v_rdev; 69839668Smckusick else 69939668Smckusick bp->b_dev = NODEV; 70039668Smckusick /* 70139668Smckusick * Insert onto list for new vnode. 70239668Smckusick */ 70339882Smckusick if (vp->v_cleanblkhd) { 70439882Smckusick bp->b_blockf = vp->v_cleanblkhd; 70539882Smckusick bp->b_blockb = &vp->v_cleanblkhd; 70639882Smckusick vp->v_cleanblkhd->b_blockb = &bp->b_blockf; 70739882Smckusick vp->v_cleanblkhd = bp; 70839668Smckusick } else { 70939882Smckusick vp->v_cleanblkhd = bp; 71039882Smckusick bp->b_blockb = &vp->v_cleanblkhd; 71139668Smckusick bp->b_blockf = NULL; 71239668Smckusick } 71339668Smckusick } 71439668Smckusick 71539668Smckusick /* 71639668Smckusick * Disassociate a buffer from a vnode. 71739668Smckusick */ 71837736Smckusick brelvp(bp) 71939668Smckusick register struct buf *bp; 72037736Smckusick { 72139668Smckusick struct buf *bq; 72237736Smckusick struct vnode *vp; 72337736Smckusick 72437736Smckusick if (bp->b_vp == (struct vnode *) 0) 72539668Smckusick panic("brelvp: NULL"); 72639668Smckusick /* 72739668Smckusick * Delete from old vnode list, if on one. 72839668Smckusick */ 72939668Smckusick if (bp->b_blockb) { 73039668Smckusick if (bq = bp->b_blockf) 73139668Smckusick bq->b_blockb = bp->b_blockb; 73239668Smckusick *bp->b_blockb = bq; 73339668Smckusick bp->b_blockf = NULL; 73439668Smckusick bp->b_blockb = NULL; 73539668Smckusick } 73637736Smckusick vp = bp->b_vp; 73737736Smckusick bp->b_vp = (struct vnode *) 0; 73839808Smckusick HOLDRELE(vp); 73937736Smckusick } 74039668Smckusick 74139668Smckusick /* 74239668Smckusick * Reassign a buffer from one vnode to another. 74339668Smckusick * Used to assign file specific control information 74439668Smckusick * (indirect blocks) to the vnode to which they belong. 74539668Smckusick */ 74639668Smckusick reassignbuf(bp, newvp) 74739668Smckusick register struct buf *bp; 74839668Smckusick register struct vnode *newvp; 74939668Smckusick { 75039882Smckusick register struct buf *bq, **listheadp; 75139668Smckusick 75239882Smckusick if (newvp == NULL) 75339882Smckusick panic("reassignbuf: NULL"); 75439668Smckusick /* 75539668Smckusick * Delete from old vnode list, if on one. 75639668Smckusick */ 75739668Smckusick if (bp->b_blockb) { 75839668Smckusick if (bq = bp->b_blockf) 75939668Smckusick bq->b_blockb = bp->b_blockb; 76039668Smckusick *bp->b_blockb = bq; 76139668Smckusick } 76239668Smckusick /* 76339882Smckusick * If dirty, put on list of dirty buffers; 76439882Smckusick * otherwise insert onto list of clean buffers. 76539668Smckusick */ 76639882Smckusick if (bp->b_flags & B_DELWRI) 76739882Smckusick listheadp = &newvp->v_dirtyblkhd; 76839882Smckusick else 76939882Smckusick listheadp = &newvp->v_cleanblkhd; 77039882Smckusick if (*listheadp) { 77139882Smckusick bp->b_blockf = *listheadp; 77239882Smckusick bp->b_blockb = listheadp; 77339882Smckusick bp->b_blockf->b_blockb = &bp->b_blockf; 77439882Smckusick *listheadp = bp; 77539668Smckusick } else { 77639882Smckusick *listheadp = bp; 77739882Smckusick bp->b_blockb = listheadp; 77839668Smckusick bp->b_blockf = NULL; 77939668Smckusick } 78039668Smckusick } 781