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*40639Smckusick * @(#)vfs_cluster.c 7.24 (Berkeley) 03/27/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)) { 4440341Smckusick trace(TR_BREADHIT, pack(vp, 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); 5540341Smckusick trace(TR_BREADMISS, pack(vp, 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); 9040341Smckusick trace(TR_BREADMISS, pack(vp, size), blkno); 918039Sroot u.u_ru.ru_inblock++; /* pay for read */ 927015Smckusick } else 9340341Smckusick trace(TR_BREADHIT, pack(vp, size), blkno); 948Sbill } 957015Smckusick 967015Smckusick /* 977015Smckusick * If there's a read-ahead block, start i/o 987015Smckusick * on it also (as above). 997015Smckusick */ 10039895Smckusick if (!incore(vp, rablkno)) { 10137736Smckusick rabp = getblk(vp, rablkno, rabsize); 10232608Smckusick if (rabp->b_flags & (B_DONE|B_DELWRI)) { 1038Sbill brelse(rabp); 10440341Smckusick trace(TR_BREADHITRA, pack(vp, rabsize), rablkno); 1052045Swnj } else { 1068Sbill rabp->b_flags |= B_READ|B_ASYNC; 1078670S if (rabp->b_bcount > rabp->b_bufsize) 1088670S panic("breadrabp"); 10938880Smckusick if (rabp->b_rcred == NOCRED && cred != NOCRED) { 11038776Smckusick crhold(cred); 11138880Smckusick rabp->b_rcred = cred; 11238776Smckusick } 11337736Smckusick VOP_STRATEGY(rabp); 11440341Smckusick trace(TR_BREADMISSRA, pack(vp, rabsize), rablkno); 1158039Sroot u.u_ru.ru_inblock++; /* pay in advance */ 1168Sbill } 1178Sbill } 1187015Smckusick 1197015Smckusick /* 1207114Smckusick * If block was in core, let bread get it. 1217114Smckusick * If block wasn't in core, then the read was started 1227114Smckusick * above, and just wait for it. 1237015Smckusick */ 1247114Smckusick if (bp == NULL) 12538776Smckusick return (bread(vp, blkno, size, cred, bpp)); 12637736Smckusick return (biowait(bp)); 1278Sbill } 1288Sbill 1298Sbill /* 1308Sbill * Write the buffer, waiting for completion. 1318Sbill * Then release the buffer. 1328Sbill */ 1338Sbill bwrite(bp) 1347015Smckusick register struct buf *bp; 1358Sbill { 13637736Smckusick register int flag; 13740226Smckusick int s, error; 1388Sbill 1398Sbill flag = bp->b_flags; 1409857Ssam bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI); 1418Sbill if ((flag&B_DELWRI) == 0) 1428039Sroot u.u_ru.ru_oublock++; /* noone paid yet */ 14339882Smckusick else 14439882Smckusick reassignbuf(bp, bp->b_vp); 14540341Smckusick trace(TR_BWRITE, pack(bp->b_vp, bp->b_bcount), bp->b_lblkno); 1468670S if (bp->b_bcount > bp->b_bufsize) 1478670S panic("bwrite"); 14840226Smckusick s = splbio(); 14939882Smckusick bp->b_vp->v_numoutput++; 15040226Smckusick splx(s); 15137736Smckusick VOP_STRATEGY(bp); 1527015Smckusick 1537015Smckusick /* 1547015Smckusick * If the write was synchronous, then await i/o completion. 1557015Smckusick * If the write was "delayed", then we put the buffer on 1567015Smckusick * the q of blocks awaiting i/o completion status. 1577015Smckusick */ 1588Sbill if ((flag&B_ASYNC) == 0) { 15937736Smckusick error = biowait(bp); 1608Sbill brelse(bp); 16137736Smckusick } else if (flag & B_DELWRI) { 1628Sbill bp->b_flags |= B_AGE; 16337736Smckusick error = 0; 16437736Smckusick } 16537736Smckusick return (error); 1668Sbill } 1678Sbill 1688Sbill /* 1698Sbill * Release the buffer, marking it so that if it is grabbed 1708Sbill * for another purpose it will be written out before being 1718Sbill * given up (e.g. when writing a partial block where it is 1728Sbill * assumed that another write for the same block will soon follow). 1738Sbill * This can't be done for magtape, since writes must be done 1748Sbill * in the same order as requested. 1758Sbill */ 1768Sbill bdwrite(bp) 1777015Smckusick register struct buf *bp; 1788Sbill { 1798Sbill 18039882Smckusick if ((bp->b_flags & B_DELWRI) == 0) { 18139882Smckusick bp->b_flags |= B_DELWRI; 18239882Smckusick reassignbuf(bp, bp->b_vp); 1838039Sroot u.u_ru.ru_oublock++; /* noone paid yet */ 18439882Smckusick } 18537736Smckusick /* 18639668Smckusick * If this is a tape drive, the write must be initiated. 18737736Smckusick */ 18839668Smckusick if (VOP_IOCTL(bp->b_vp, 0, B_TAPE, 0, NOCRED) == 0) { 1898Sbill bawrite(bp); 19039668Smckusick } else { 1918Sbill bp->b_flags |= B_DELWRI | B_DONE; 1928Sbill brelse(bp); 1938Sbill } 1948Sbill } 1958Sbill 1968Sbill /* 1978Sbill * Release the buffer, start I/O on it, but don't wait for completion. 1988Sbill */ 1998Sbill bawrite(bp) 2007015Smckusick register struct buf *bp; 2018Sbill { 2028Sbill 2038Sbill bp->b_flags |= B_ASYNC; 20437736Smckusick (void) bwrite(bp); 2058Sbill } 2068Sbill 2078Sbill /* 2087015Smckusick * Release the buffer, with no I/O implied. 2098Sbill */ 2108Sbill brelse(bp) 2117015Smckusick register struct buf *bp; 2128Sbill { 2132325Swnj register struct buf *flist; 2148Sbill register s; 2158Sbill 21640341Smckusick trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno); 2177015Smckusick /* 21839668Smckusick * If a process is waiting for the buffer, or 21939668Smckusick * is waiting for a free buffer, awaken it. 2207015Smckusick */ 2218Sbill if (bp->b_flags&B_WANTED) 2228Sbill wakeup((caddr_t)bp); 2232325Swnj if (bfreelist[0].b_flags&B_WANTED) { 2242325Swnj bfreelist[0].b_flags &= ~B_WANTED; 2252325Swnj wakeup((caddr_t)bfreelist); 2268Sbill } 22739668Smckusick /* 22839668Smckusick * Retry I/O for locked buffers rather than invalidating them. 22939668Smckusick */ 23039668Smckusick if ((bp->b_flags & B_ERROR) && (bp->b_flags & B_LOCKED)) 23139668Smckusick bp->b_flags &= ~B_ERROR; 23239668Smckusick 23339668Smckusick /* 23439668Smckusick * Disassociate buffers that are no longer valid. 23539668Smckusick */ 23639668Smckusick if (bp->b_flags & (B_NOCACHE|B_ERROR)) 23737736Smckusick bp->b_flags |= B_INVAL; 23839668Smckusick 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); 2518670S } 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 } 26437736Smckusick bp->b_flags &= ~(B_WANTED|B_BUSY|B_ASYNC|B_AGE|B_NOCACHE); 2658Sbill splx(s); 2668Sbill } 2678Sbill 2688Sbill /* 2698Sbill * See if the block is associated with some buffer 2708Sbill * (mainly to avoid getting hung up on a wait in breada) 2718Sbill */ 27237736Smckusick incore(vp, blkno) 27337736Smckusick struct vnode *vp; 2747015Smckusick daddr_t blkno; 2758Sbill { 2768Sbill register struct buf *bp; 2772325Swnj register struct buf *dp; 2788Sbill 27938225Smckusick dp = BUFHASH(vp, blkno); 2802325Swnj for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) 28139668Smckusick if (bp->b_lblkno == blkno && bp->b_vp == vp && 2827015Smckusick (bp->b_flags & B_INVAL) == 0) 28391Sbill return (1); 28491Sbill return (0); 2858Sbill } 2868Sbill 28739668Smckusick /* 28839668Smckusick * Return a block if it is in memory. 28939668Smckusick */ 29038776Smckusick baddr(vp, blkno, size, cred, bpp) 29137736Smckusick struct vnode *vp; 2926563Smckusic daddr_t blkno; 2936563Smckusic int size; 29438776Smckusick struct ucred *cred; 29537736Smckusick struct buf **bpp; 2968Sbill { 2978Sbill 29837736Smckusick if (incore(vp, blkno)) 29938776Smckusick return (bread(vp, blkno, size, cred, bpp)); 30037736Smckusick *bpp = 0; 3018Sbill return (0); 3028Sbill } 3038Sbill 3048Sbill /* 3058Sbill * Assign a buffer for the given block. If the appropriate 3068Sbill * block is already associated, return it; otherwise search 3078Sbill * for the oldest non-busy buffer and reassign it. 3085424Swnj * 3095424Swnj * We use splx here because this routine may be called 3105424Swnj * on the interrupt stack during a dump, and we don't 3115424Swnj * want to lower the ipl back to 0. 3128Sbill */ 3138Sbill struct buf * 31437736Smckusick getblk(vp, blkno, size) 31537736Smckusick register struct vnode *vp; 3166563Smckusic daddr_t blkno; 3176563Smckusic int size; 3188Sbill { 3198670S register struct buf *bp, *dp; 3205424Swnj int s; 3218Sbill 32225255Smckusick if (size > MAXBSIZE) 32325255Smckusick panic("getblk: size too big"); 3247015Smckusick /* 32524730Smckusick * To prevent overflow of 32-bit ints when converting block 32624730Smckusick * numbers to byte offsets, blknos > 2^32 / DEV_BSIZE are set 32724730Smckusick * to the maximum number that can be converted to a byte offset 32824730Smckusick * without overflow. This is historic code; what bug it fixed, 32924730Smckusick * or whether it is still a reasonable thing to do is open to 33024730Smckusick * dispute. mkm 9/85 33139668Smckusick * 33239668Smckusick * Make it a panic to see if it ever really happens. mkm 11/89 33324730Smckusick */ 33439668Smckusick if ((unsigned)blkno >= 1 << (sizeof(int)*NBBY-DEV_BSHIFT)) { 33539668Smckusick panic("getblk: blkno too big"); 33624730Smckusick blkno = 1 << ((sizeof(int)*NBBY-DEV_BSHIFT) + 1); 33739668Smckusick } 33824730Smckusick /* 3397015Smckusick * Search the cache for the block. If we hit, but 3407015Smckusick * the buffer is in use for i/o, then we wait until 3417015Smckusick * the i/o has completed. 3427015Smckusick */ 34337736Smckusick dp = BUFHASH(vp, blkno); 3447015Smckusick loop: 3452325Swnj for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) { 34639668Smckusick if (bp->b_lblkno != blkno || bp->b_vp != vp || 3472325Swnj bp->b_flags&B_INVAL) 3488Sbill continue; 34926271Skarels s = splbio(); 3508Sbill if (bp->b_flags&B_BUSY) { 3518Sbill bp->b_flags |= B_WANTED; 3528Sbill sleep((caddr_t)bp, PRIBIO+1); 3535424Swnj splx(s); 3548Sbill goto loop; 3558Sbill } 35639882Smckusick bremfree(bp); 35739882Smckusick bp->b_flags |= B_BUSY; 3585424Swnj splx(s); 35932608Smckusick if (bp->b_bcount != size) { 36039668Smckusick printf("getblk: stray size"); 36139668Smckusick bp->b_flags |= B_INVAL; 36239668Smckusick bwrite(bp); 36339668Smckusick goto loop; 36432608Smckusick } 3658Sbill bp->b_flags |= B_CACHE; 36626271Skarels return (bp); 3678Sbill } 3688670S bp = getnewbuf(); 3696563Smckusic bfree(bp); 3707015Smckusick bremhash(bp); 37139668Smckusick bgetvp(vp, bp); 37239668Smckusick bp->b_lblkno = blkno; 3736563Smckusic bp->b_blkno = blkno; 3748670S bp->b_error = 0; 37537736Smckusick bp->b_resid = 0; 37637736Smckusick binshash(bp, dp); 37739668Smckusick brealloc(bp, size); 37826271Skarels return (bp); 3798Sbill } 3808Sbill 3818Sbill /* 3828Sbill * get an empty block, 3838Sbill * not assigned to any particular device 3848Sbill */ 3858Sbill struct buf * 3866563Smckusic geteblk(size) 3876563Smckusic int size; 3888Sbill { 3898670S register struct buf *bp, *flist; 3908Sbill 39125255Smckusick if (size > MAXBSIZE) 39225255Smckusick panic("geteblk: size too big"); 3938670S bp = getnewbuf(); 3948670S bp->b_flags |= B_INVAL; 3957015Smckusick bfree(bp); 3967015Smckusick bremhash(bp); 3978670S flist = &bfreelist[BQ_AGE]; 39837736Smckusick bp->b_error = 0; 39937736Smckusick bp->b_resid = 0; 4008670S binshash(bp, flist); 40139668Smckusick brealloc(bp, size); 40226271Skarels return (bp); 4038Sbill } 4048Sbill 4058Sbill /* 4066563Smckusic * Allocate space associated with a buffer. 4076563Smckusic */ 4086563Smckusic brealloc(bp, size) 4096563Smckusic register struct buf *bp; 4106563Smckusic int size; 4116563Smckusic { 4126563Smckusic daddr_t start, last; 4136563Smckusic register struct buf *ep; 4146563Smckusic struct buf *dp; 4156563Smckusic int s; 4166563Smckusic 4176563Smckusic if (size == bp->b_bcount) 41839668Smckusick return; 41939668Smckusick allocbuf(bp, size); 4208670S } 4218670S 4228670S /* 4238670S * Find a buffer which is available for use. 4248670S * Select something from a free list. 4258670S * Preference is to AGE list, then LRU list. 4268670S */ 4278670S struct buf * 4288670S getnewbuf() 4298670S { 4308670S register struct buf *bp, *dp; 43138776Smckusick register struct ucred *cred; 4328670S int s; 4338670S 4348670S loop: 43526271Skarels s = splbio(); 4368670S for (dp = &bfreelist[BQ_AGE]; dp > bfreelist; dp--) 4378670S if (dp->av_forw != dp) 4388670S break; 4398670S if (dp == bfreelist) { /* no free blocks */ 4408670S dp->b_flags |= B_WANTED; 4418670S sleep((caddr_t)dp, PRIBIO+1); 44212170Ssam splx(s); 4438670S goto loop; 4448670S } 44539882Smckusick bp = dp->av_forw; 44639882Smckusick bremfree(bp); 44739882Smckusick bp->b_flags |= B_BUSY; 4488670S splx(s); 4498670S if (bp->b_flags & B_DELWRI) { 45038614Smckusick (void) bawrite(bp); 4518670S goto loop; 4528670S } 45340341Smckusick trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno); 45439668Smckusick if (bp->b_vp) 45539668Smckusick brelvp(bp); 45638776Smckusick if (bp->b_rcred != NOCRED) { 45738776Smckusick cred = bp->b_rcred; 45838776Smckusick bp->b_rcred = NOCRED; 45938776Smckusick crfree(cred); 46038776Smckusick } 46138776Smckusick if (bp->b_wcred != NOCRED) { 46238776Smckusick cred = bp->b_wcred; 46338776Smckusick bp->b_wcred = NOCRED; 46438776Smckusick crfree(cred); 46538776Smckusick } 4668670S bp->b_flags = B_BUSY; 4678670S return (bp); 4688670S } 4698670S 4708670S /* 4718Sbill * Wait for I/O completion on the buffer; return errors 4728Sbill * to the user. 4738Sbill */ 4747015Smckusick biowait(bp) 4756563Smckusic register struct buf *bp; 4768Sbill { 4775431Sroot int s; 4788Sbill 47926271Skarels s = splbio(); 48038776Smckusick while ((bp->b_flags & B_DONE) == 0) 4818Sbill sleep((caddr_t)bp, PRIBIO); 4825431Sroot splx(s); 48337736Smckusick /* 48437736Smckusick * Pick up the device's error number and pass it to the user; 48537736Smckusick * if there is an error but the number is 0 set a generalized code. 48637736Smckusick */ 48737736Smckusick if ((bp->b_flags & B_ERROR) == 0) 48837736Smckusick return (0); 48937736Smckusick if (bp->b_error) 49037736Smckusick return (bp->b_error); 49137736Smckusick return (EIO); 4928Sbill } 4938Sbill 4948Sbill /* 49513128Ssam * Mark I/O complete on a buffer. 49613128Ssam * If someone should be called, e.g. the pageout 49713128Ssam * daemon, do so. Otherwise, wake up anyone 49813128Ssam * waiting for it. 4998Sbill */ 5007015Smckusick biodone(bp) 5017015Smckusick register struct buf *bp; 5028Sbill { 50339882Smckusick register struct vnode *vp; 5048Sbill 505420Sbill if (bp->b_flags & B_DONE) 5067015Smckusick panic("dup biodone"); 5078Sbill bp->b_flags |= B_DONE; 50839882Smckusick if ((bp->b_flags & B_READ) == 0) { 50938776Smckusick bp->b_dirtyoff = bp->b_dirtyend = 0; 51039882Smckusick if (vp = bp->b_vp) { 51139882Smckusick vp->v_numoutput--; 51239882Smckusick if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) { 51339882Smckusick if (vp->v_numoutput < 0) 51439882Smckusick panic("biodone: neg numoutput"); 51539882Smckusick vp->v_flag &= ~VBWAIT; 51639882Smckusick wakeup((caddr_t)&vp->v_numoutput); 51739882Smckusick } 51839882Smckusick } 51939882Smckusick } 5209763Ssam if (bp->b_flags & B_CALL) { 5219763Ssam bp->b_flags &= ~B_CALL; 5229763Ssam (*bp->b_iodone)(bp); 5239763Ssam return; 5249763Ssam } 5258Sbill if (bp->b_flags&B_ASYNC) 5268Sbill brelse(bp); 5278Sbill else { 5288Sbill bp->b_flags &= ~B_WANTED; 5298Sbill wakeup((caddr_t)bp); 5308Sbill } 5318Sbill } 5328Sbill 5338Sbill /* 53437736Smckusick * Make sure all write-behind blocks associated 53538776Smckusick * with mount point are flushed out (from sync). 5368Sbill */ 53739668Smckusick mntflushbuf(mountp, flags) 53838776Smckusick struct mount *mountp; 53939668Smckusick int flags; 5408Sbill { 54139668Smckusick register struct vnode *vp; 54239764Smckusick struct vnode *nvp; 54339668Smckusick 54439668Smckusick loop: 54539764Smckusick for (vp = mountp->m_mounth; vp; vp = nvp) { 54639764Smckusick nvp = vp->v_mountf; 54739668Smckusick if (vget(vp)) 54839668Smckusick goto loop; 54939668Smckusick vflushbuf(vp, flags); 55039668Smckusick vput(vp); 55139668Smckusick } 55239668Smckusick } 55339668Smckusick 55439668Smckusick /* 55539668Smckusick * Flush all dirty buffers associated with a vnode. 55639668Smckusick */ 55739668Smckusick vflushbuf(vp, flags) 55839668Smckusick register struct vnode *vp; 55939668Smckusick int flags; 56039668Smckusick { 5618Sbill register struct buf *bp; 56239668Smckusick struct buf *nbp; 5635431Sroot int s; 5648Sbill 5658Sbill loop: 56626271Skarels s = splbio(); 56739882Smckusick for (bp = vp->v_dirtyblkhd; bp; bp = nbp) { 56839668Smckusick nbp = bp->b_blockf; 56939668Smckusick if ((bp->b_flags & B_BUSY)) 57039668Smckusick continue; 57139668Smckusick if ((bp->b_flags & B_DELWRI) == 0) 57239882Smckusick panic("vflushbuf: not dirty"); 57339882Smckusick bremfree(bp); 57439882Smckusick bp->b_flags |= B_BUSY; 57539668Smckusick splx(s); 57639882Smckusick /* 57739882Smckusick * Wait for I/O associated with indirect blocks to complete, 57839882Smckusick * since there is no way to quickly wait for them below. 57939882Smckusick * NB - This is really specific to ufs, but is done here 58039882Smckusick * as it is easier and quicker. 58139882Smckusick */ 58239882Smckusick if (bp->b_vp == vp || (flags & B_SYNC) == 0) { 58339882Smckusick (void) bawrite(bp); 584*40639Smckusick s = splbio(); 58539882Smckusick } else { 58639882Smckusick (void) bwrite(bp); 58739882Smckusick goto loop; 58839882Smckusick } 58939668Smckusick } 59039738Smckusick splx(s); 59139668Smckusick if ((flags & B_SYNC) == 0) 59239668Smckusick return; 59339668Smckusick s = splbio(); 59439882Smckusick while (vp->v_numoutput) { 59539882Smckusick vp->v_flag |= VBWAIT; 59639882Smckusick sleep((caddr_t)&vp->v_numoutput, PRIBIO+1); 59737736Smckusick } 59839738Smckusick splx(s); 59939882Smckusick if (vp->v_dirtyblkhd) { 60039882Smckusick vprint("vflushbuf: dirty", vp); 60139882Smckusick goto loop; 60239882Smckusick } 6038Sbill } 6042299Skre 6052299Skre /* 6062299Skre * Invalidate in core blocks belonging to closed or umounted filesystem 6072299Skre * 60839668Smckusick * Go through the list of vnodes associated with the file system; 60939668Smckusick * for each vnode invalidate any buffers that it holds. Normally 61039668Smckusick * this routine is preceeded by a bflush call, so that on a quiescent 61139668Smckusick * filesystem there will be no dirty buffers when we are done. Binval 61239668Smckusick * returns the count of dirty buffers when it is finished. 6132299Skre */ 61439668Smckusick mntinvalbuf(mountp) 61538776Smckusick struct mount *mountp; 6162299Skre { 61739668Smckusick register struct vnode *vp; 61839764Smckusick struct vnode *nvp; 61939668Smckusick int dirty = 0; 62039668Smckusick 62139668Smckusick loop: 62239764Smckusick for (vp = mountp->m_mounth; vp; vp = nvp) { 62339764Smckusick nvp = vp->v_mountf; 62439668Smckusick if (vget(vp)) 62539668Smckusick goto loop; 62639668Smckusick dirty += vinvalbuf(vp, 1); 62739668Smckusick vput(vp); 62839668Smckusick } 62939668Smckusick return (dirty); 63039668Smckusick } 63139668Smckusick 63239668Smckusick /* 63339668Smckusick * Flush out and invalidate all buffers associated with a vnode. 63439668Smckusick * Called with the underlying object locked. 63539668Smckusick */ 63639668Smckusick vinvalbuf(vp, save) 63739668Smckusick register struct vnode *vp; 63839668Smckusick int save; 63939668Smckusick { 6402361Skre register struct buf *bp; 64139882Smckusick struct buf *nbp, *blist; 64238633Smckusick int s, dirty = 0; 6432299Skre 64439882Smckusick for (;;) { 64539882Smckusick if (blist = vp->v_dirtyblkhd) 64639882Smckusick /* void */; 64739882Smckusick else if (blist = vp->v_cleanblkhd) 64839882Smckusick /* void */; 64939882Smckusick else 65039882Smckusick break; 65139882Smckusick for (bp = blist; bp; bp = nbp) { 65239882Smckusick nbp = bp->b_blockf; 65339882Smckusick s = splbio(); 65439882Smckusick if (bp->b_flags & B_BUSY) { 65539882Smckusick bp->b_flags |= B_WANTED; 65639882Smckusick sleep((caddr_t)bp, PRIBIO+1); 65739882Smckusick splx(s); 65839882Smckusick break; 65939882Smckusick } 66039882Smckusick bremfree(bp); 66139882Smckusick bp->b_flags |= B_BUSY; 66238808Smckusick splx(s); 66339882Smckusick if (save && (bp->b_flags & B_DELWRI)) { 66438614Smckusick dirty++; 66539668Smckusick (void) bwrite(bp); 66639882Smckusick break; 66737736Smckusick } 66840034Smckusick if (bp->b_vp != vp) 66940034Smckusick reassignbuf(bp, bp->b_vp); 67040034Smckusick else 67140034Smckusick bp->b_flags |= B_INVAL; 67239882Smckusick brelse(bp); 67338614Smckusick } 67438614Smckusick } 67539882Smckusick if (vp->v_dirtyblkhd || vp->v_cleanblkhd) 67639668Smckusick panic("vinvalbuf: flush failed"); 67738614Smckusick return (dirty); 6782299Skre } 67937736Smckusick 68039668Smckusick /* 68139668Smckusick * Associate a buffer with a vnode. 68239668Smckusick */ 68339668Smckusick bgetvp(vp, bp) 68439668Smckusick register struct vnode *vp; 68539668Smckusick register struct buf *bp; 68639668Smckusick { 68739668Smckusick 68839668Smckusick if (bp->b_vp) 68939668Smckusick panic("bgetvp: not free"); 69039808Smckusick VHOLD(vp); 69139668Smckusick bp->b_vp = vp; 69239668Smckusick if (vp->v_type == VBLK || vp->v_type == VCHR) 69339668Smckusick bp->b_dev = vp->v_rdev; 69439668Smckusick else 69539668Smckusick bp->b_dev = NODEV; 69639668Smckusick /* 69739668Smckusick * Insert onto list for new vnode. 69839668Smckusick */ 69939882Smckusick if (vp->v_cleanblkhd) { 70039882Smckusick bp->b_blockf = vp->v_cleanblkhd; 70139882Smckusick bp->b_blockb = &vp->v_cleanblkhd; 70239882Smckusick vp->v_cleanblkhd->b_blockb = &bp->b_blockf; 70339882Smckusick vp->v_cleanblkhd = bp; 70439668Smckusick } else { 70539882Smckusick vp->v_cleanblkhd = bp; 70639882Smckusick bp->b_blockb = &vp->v_cleanblkhd; 70739668Smckusick bp->b_blockf = NULL; 70839668Smckusick } 70939668Smckusick } 71039668Smckusick 71139668Smckusick /* 71239668Smckusick * Disassociate a buffer from a vnode. 71339668Smckusick */ 71437736Smckusick brelvp(bp) 71539668Smckusick register struct buf *bp; 71637736Smckusick { 71739668Smckusick struct buf *bq; 71837736Smckusick struct vnode *vp; 71937736Smckusick 72037736Smckusick if (bp->b_vp == (struct vnode *) 0) 72139668Smckusick panic("brelvp: NULL"); 72239668Smckusick /* 72339668Smckusick * Delete from old vnode list, if on one. 72439668Smckusick */ 72539668Smckusick if (bp->b_blockb) { 72639668Smckusick if (bq = bp->b_blockf) 72739668Smckusick bq->b_blockb = bp->b_blockb; 72839668Smckusick *bp->b_blockb = bq; 72939668Smckusick bp->b_blockf = NULL; 73039668Smckusick bp->b_blockb = NULL; 73139668Smckusick } 73237736Smckusick vp = bp->b_vp; 73337736Smckusick bp->b_vp = (struct vnode *) 0; 73439808Smckusick HOLDRELE(vp); 73537736Smckusick } 73639668Smckusick 73739668Smckusick /* 73839668Smckusick * Reassign a buffer from one vnode to another. 73939668Smckusick * Used to assign file specific control information 74039668Smckusick * (indirect blocks) to the vnode to which they belong. 74139668Smckusick */ 74239668Smckusick reassignbuf(bp, newvp) 74339668Smckusick register struct buf *bp; 74439668Smckusick register struct vnode *newvp; 74539668Smckusick { 74639882Smckusick register struct buf *bq, **listheadp; 74739668Smckusick 74839882Smckusick if (newvp == NULL) 74939882Smckusick panic("reassignbuf: NULL"); 75039668Smckusick /* 75139668Smckusick * Delete from old vnode list, if on one. 75239668Smckusick */ 75339668Smckusick if (bp->b_blockb) { 75439668Smckusick if (bq = bp->b_blockf) 75539668Smckusick bq->b_blockb = bp->b_blockb; 75639668Smckusick *bp->b_blockb = bq; 75739668Smckusick } 75839668Smckusick /* 75939882Smckusick * If dirty, put on list of dirty buffers; 76039882Smckusick * otherwise insert onto list of clean buffers. 76139668Smckusick */ 76239882Smckusick if (bp->b_flags & B_DELWRI) 76339882Smckusick listheadp = &newvp->v_dirtyblkhd; 76439882Smckusick else 76539882Smckusick listheadp = &newvp->v_cleanblkhd; 76639882Smckusick if (*listheadp) { 76739882Smckusick bp->b_blockf = *listheadp; 76839882Smckusick bp->b_blockb = listheadp; 76939882Smckusick bp->b_blockf->b_blockb = &bp->b_blockf; 77039882Smckusick *listheadp = bp; 77139668Smckusick } else { 77239882Smckusick *listheadp = bp; 77339882Smckusick bp->b_blockb = listheadp; 77439668Smckusick bp->b_blockf = NULL; 77539668Smckusick } 77639668Smckusick } 777