149589Sbostic /*- 249589Sbostic * Copyright (c) 1982, 1986, 1989 The Regents of the University of California. 337736Smckusick * All rights reserved. 423395Smckusick * 549618Smckusick * This module is believed to contain source code proprietary to AT&T. 649618Smckusick * Use and redistribution is subject to the Berkeley Software License 749618Smckusick * Agreement and your Software Agreement with AT&T (Western Electric). 837736Smckusick * 9*57035Smargo * @(#)vfs_cluster.c 7.56 (Berkeley) 12/09/92 1023395Smckusick */ 118Sbill 1251455Sbostic #include <sys/param.h> 1351455Sbostic #include <sys/proc.h> 1451455Sbostic #include <sys/buf.h> 1551455Sbostic #include <sys/vnode.h> 1651455Sbostic #include <sys/mount.h> 1751455Sbostic #include <sys/trace.h> 1851455Sbostic #include <sys/resourcevar.h> 1956395Smckusick #include <sys/malloc.h> 2056395Smckusick #include <libkern/libkern.h> 218Sbill 2291Sbill /* 2356395Smckusick * Definitions for the buffer hash lists. 2456395Smckusick */ 2556395Smckusick #define BUFHASH(dvp, lbn) \ 2656395Smckusick (&bufhashtbl[((int)(dvp) / sizeof(*(dvp)) + (int)(lbn)) & bufhash]) 2756607Smckusick struct list_entry *bufhashtbl, invalhash; 2856395Smckusick u_long bufhash; 2956395Smckusick 3056395Smckusick /* 3156395Smckusick * Insq/Remq for the buffer hash lists. 3256395Smckusick */ 3356607Smckusick #define binshash(bp, dp) list_enter_head(dp, bp, struct buf *, b_hash) 3456607Smckusick #define bremhash(bp) list_remove(bp, struct buf *, b_hash) 3556395Smckusick 3656395Smckusick /* 3756395Smckusick * Definitions for the buffer free lists. 3856395Smckusick */ 3956395Smckusick #define BQUEUES 4 /* number of free buffer queues */ 4056395Smckusick 4156395Smckusick #define BQ_LOCKED 0 /* super-blocks &c */ 4256395Smckusick #define BQ_LRU 1 /* lru, useful buffers */ 4356395Smckusick #define BQ_AGE 2 /* rubbish */ 4456395Smckusick #define BQ_EMPTY 3 /* buffer headers with no memory */ 4556395Smckusick 4656607Smckusick struct queue_entry bufqueues[BQUEUES]; 4756395Smckusick int needbuffer; 4856395Smckusick 4956395Smckusick /* 5056395Smckusick * Insq/Remq for the buffer free lists. 5156395Smckusick */ 5256607Smckusick #define binsheadfree(bp, dp) \ 5356607Smckusick queue_enter_head(dp, bp, struct buf *, b_freelist) 5456607Smckusick #define binstailfree(bp, dp) \ 5556607Smckusick queue_enter_tail(dp, bp, struct buf *, b_freelist) 5656607Smckusick 5756395Smckusick void 5856395Smckusick bremfree(bp) 5956395Smckusick struct buf *bp; 6056395Smckusick { 6156607Smckusick struct queue_entry *dp; 6256395Smckusick 6356607Smckusick /* 6456607Smckusick * We only calculate the head of the freelist when removing 6556607Smckusick * the last element of the list as that is the only time that 6656607Smckusick * it is needed (e.g. to reset the tail pointer). 6756607Smckusick */ 6856607Smckusick if (bp->b_freelist.qe_next == NULL) { 6956395Smckusick for (dp = bufqueues; dp < &bufqueues[BQUEUES]; dp++) 7056607Smckusick if (dp->qe_prev == &bp->b_freelist.qe_next) 7156395Smckusick break; 7256395Smckusick if (dp == &bufqueues[BQUEUES]) 7356395Smckusick panic("bremfree: lost tail"); 7456395Smckusick } 7556607Smckusick queue_remove(dp, bp, struct buf *, b_freelist); 7656395Smckusick } 7756395Smckusick 7856395Smckusick /* 7949280Skarels * Initialize buffers and hash links for buffers. 8049280Skarels */ 8151455Sbostic void 8249280Skarels bufinit() 8349280Skarels { 8456395Smckusick register struct buf *bp; 8556607Smckusick struct queue_entry *dp; 8649280Skarels register int i; 8749280Skarels int base, residual; 8849280Skarels 8956395Smckusick for (dp = bufqueues; dp < &bufqueues[BQUEUES]; dp++) 9056607Smckusick queue_init(dp); 9156607Smckusick bufhashtbl = (struct list_entry *)hashinit(nbuf, M_CACHE, &bufhash); 9249280Skarels base = bufpages / nbuf; 9349280Skarels residual = bufpages % nbuf; 9449280Skarels for (i = 0; i < nbuf; i++) { 9549280Skarels bp = &buf[i]; 9656395Smckusick bzero((char *)bp, sizeof *bp); 9749280Skarels bp->b_dev = NODEV; 9849280Skarels bp->b_rcred = NOCRED; 9949280Skarels bp->b_wcred = NOCRED; 10049280Skarels bp->b_un.b_addr = buffers + i * MAXBSIZE; 10149280Skarels if (i < residual) 10249280Skarels bp->b_bufsize = (base + 1) * CLBYTES; 10349280Skarels else 10449280Skarels bp->b_bufsize = base * CLBYTES; 10552413Storek bp->b_flags = B_INVAL; 10656395Smckusick dp = bp->b_bufsize ? &bufqueues[BQ_AGE] : &bufqueues[BQ_EMPTY]; 10752413Storek binsheadfree(bp, dp); 10856395Smckusick binshash(bp, &invalhash); 10949280Skarels } 11049280Skarels } 11149280Skarels 11249280Skarels /* 11346151Smckusick * Find the block in the buffer pool. 11446151Smckusick * If the buffer is not present, allocate a new buffer and load 11546151Smckusick * its contents according to the filesystem fill routine. 1168Sbill */ 11738776Smckusick bread(vp, blkno, size, cred, bpp) 11837736Smckusick struct vnode *vp; 1196563Smckusic daddr_t blkno; 1206563Smckusic int size; 12138776Smckusick struct ucred *cred; 12237736Smckusick struct buf **bpp; 1238Sbill { 12447545Skarels struct proc *p = curproc; /* XXX */ 1258Sbill register struct buf *bp; 1268Sbill 1278670S if (size == 0) 1288670S panic("bread: size 0"); 12937736Smckusick *bpp = bp = getblk(vp, blkno, size); 13046151Smckusick if (bp->b_flags & (B_DONE | B_DELWRI)) { 13140341Smckusick trace(TR_BREADHIT, pack(vp, size), blkno); 13237736Smckusick return (0); 1338Sbill } 1348Sbill bp->b_flags |= B_READ; 1358670S if (bp->b_bcount > bp->b_bufsize) 1368670S panic("bread"); 13738776Smckusick if (bp->b_rcred == NOCRED && cred != NOCRED) { 13838776Smckusick crhold(cred); 13938776Smckusick bp->b_rcred = cred; 14038776Smckusick } 14137736Smckusick VOP_STRATEGY(bp); 14240341Smckusick trace(TR_BREADMISS, pack(vp, size), blkno); 14347545Skarels p->p_stats->p_ru.ru_inblock++; /* pay for read */ 14437736Smckusick return (biowait(bp)); 1458Sbill } 1468Sbill 1478Sbill /* 14852189Smckusick * Operates like bread, but also starts I/O on the N specified 14952189Smckusick * read-ahead blocks. 1508Sbill */ 15152189Smckusick breadn(vp, blkno, size, rablkno, rabsize, num, cred, bpp) 15237736Smckusick struct vnode *vp; 1537114Smckusick daddr_t blkno; int size; 15452189Smckusick daddr_t rablkno[]; int rabsize[]; 15552189Smckusick int num; 15638776Smckusick struct ucred *cred; 15737736Smckusick struct buf **bpp; 1588Sbill { 15947545Skarels struct proc *p = curproc; /* XXX */ 1608Sbill register struct buf *bp, *rabp; 16152189Smckusick register int i; 1628Sbill 1638Sbill bp = NULL; 1647015Smckusick /* 16546151Smckusick * If the block is not memory resident, 16646151Smckusick * allocate a buffer and start I/O. 1677015Smckusick */ 16837736Smckusick if (!incore(vp, blkno)) { 16937736Smckusick *bpp = bp = getblk(vp, blkno, size); 17046151Smckusick if ((bp->b_flags & (B_DONE | B_DELWRI)) == 0) { 1718Sbill bp->b_flags |= B_READ; 1728670S if (bp->b_bcount > bp->b_bufsize) 17352189Smckusick panic("breadn"); 17438776Smckusick if (bp->b_rcred == NOCRED && cred != NOCRED) { 17538776Smckusick crhold(cred); 17638776Smckusick bp->b_rcred = cred; 17738776Smckusick } 17837736Smckusick VOP_STRATEGY(bp); 17940341Smckusick trace(TR_BREADMISS, pack(vp, size), blkno); 18047545Skarels p->p_stats->p_ru.ru_inblock++; /* pay for read */ 18154342Smckusick } else { 18240341Smckusick trace(TR_BREADHIT, pack(vp, size), blkno); 18354342Smckusick } 1848Sbill } 1857015Smckusick 1867015Smckusick /* 18752189Smckusick * If there's read-ahead block(s), start I/O 18852189Smckusick * on them also (as above). 1897015Smckusick */ 19052189Smckusick for (i = 0; i < num; i++) { 19152189Smckusick if (incore(vp, rablkno[i])) 19252189Smckusick continue; 19352189Smckusick rabp = getblk(vp, rablkno[i], rabsize[i]); 19446151Smckusick if (rabp->b_flags & (B_DONE | B_DELWRI)) { 1958Sbill brelse(rabp); 19652189Smckusick trace(TR_BREADHITRA, pack(vp, rabsize[i]), rablkno[i]); 1972045Swnj } else { 19846151Smckusick rabp->b_flags |= B_ASYNC | B_READ; 1998670S if (rabp->b_bcount > rabp->b_bufsize) 2008670S panic("breadrabp"); 20138880Smckusick if (rabp->b_rcred == NOCRED && cred != NOCRED) { 20238776Smckusick crhold(cred); 20338880Smckusick rabp->b_rcred = cred; 20438776Smckusick } 20537736Smckusick VOP_STRATEGY(rabp); 20652189Smckusick trace(TR_BREADMISSRA, pack(vp, rabsize[i]), rablkno[i]); 20747545Skarels p->p_stats->p_ru.ru_inblock++; /* pay in advance */ 2088Sbill } 2098Sbill } 2107015Smckusick 2117015Smckusick /* 21246151Smckusick * If block was memory resident, let bread get it. 21346151Smckusick * If block was not memory resident, the read was 21446151Smckusick * started above, so just wait for the read to complete. 2157015Smckusick */ 2167114Smckusick if (bp == NULL) 21738776Smckusick return (bread(vp, blkno, size, cred, bpp)); 21837736Smckusick return (biowait(bp)); 2198Sbill } 2208Sbill 2218Sbill /* 22246151Smckusick * Synchronous write. 22346151Smckusick * Release buffer on completion. 2248Sbill */ 2258Sbill bwrite(bp) 2267015Smckusick register struct buf *bp; 2278Sbill { 22847545Skarels struct proc *p = curproc; /* XXX */ 22937736Smckusick register int flag; 23052413Storek int s, error = 0; 2318Sbill 2328Sbill flag = bp->b_flags; 2339857Ssam bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI); 23449459Smckusick if (flag & B_ASYNC) { 23549459Smckusick if ((flag & B_DELWRI) == 0) 23649459Smckusick p->p_stats->p_ru.ru_oublock++; /* no one paid yet */ 23749459Smckusick else 23849459Smckusick reassignbuf(bp, bp->b_vp); 23949459Smckusick } 24040341Smckusick trace(TR_BWRITE, pack(bp->b_vp, bp->b_bcount), bp->b_lblkno); 2418670S if (bp->b_bcount > bp->b_bufsize) 2428670S panic("bwrite"); 24340226Smckusick s = splbio(); 24439882Smckusick bp->b_vp->v_numoutput++; 24540226Smckusick splx(s); 24637736Smckusick VOP_STRATEGY(bp); 2477015Smckusick 2487015Smckusick /* 24946151Smckusick * If the write was synchronous, then await I/O completion. 2507015Smckusick * If the write was "delayed", then we put the buffer on 25146151Smckusick * the queue of blocks awaiting I/O completion status. 2527015Smckusick */ 25346151Smckusick if ((flag & B_ASYNC) == 0) { 25437736Smckusick error = biowait(bp); 25549459Smckusick if ((flag&B_DELWRI) == 0) 25649459Smckusick p->p_stats->p_ru.ru_oublock++; /* no one paid yet */ 25749459Smckusick else 25849459Smckusick reassignbuf(bp, bp->b_vp); 2598Sbill brelse(bp); 26037736Smckusick } else if (flag & B_DELWRI) { 26152413Storek s = splbio(); 2628Sbill bp->b_flags |= B_AGE; 26352413Storek splx(s); 26437736Smckusick } 26537736Smckusick return (error); 2668Sbill } 2678Sbill 26853578Sheideman int 26953578Sheideman vn_bwrite(ap) 27053578Sheideman struct vop_bwrite_args *ap; 27153578Sheideman { 27256395Smckusick return (bwrite(ap->a_bp)); 27353578Sheideman } 27453578Sheideman 27553578Sheideman 2768Sbill /* 27746151Smckusick * Delayed write. 27846151Smckusick * 27946151Smckusick * The buffer is marked dirty, but is not queued for I/O. 28046151Smckusick * This routine should be used when the buffer is expected 28146151Smckusick * to be modified again soon, typically a small write that 28246151Smckusick * partially fills a buffer. 28346151Smckusick * 28446151Smckusick * NB: magnetic tapes cannot be delayed; they must be 28546151Smckusick * written in the order that the writes are requested. 2868Sbill */ 2878Sbill bdwrite(bp) 2887015Smckusick register struct buf *bp; 2898Sbill { 29047545Skarels struct proc *p = curproc; /* XXX */ 2918Sbill 29239882Smckusick if ((bp->b_flags & B_DELWRI) == 0) { 29339882Smckusick bp->b_flags |= B_DELWRI; 29439882Smckusick reassignbuf(bp, bp->b_vp); 29547545Skarels p->p_stats->p_ru.ru_oublock++; /* no one paid yet */ 29639882Smckusick } 29737736Smckusick /* 29839668Smckusick * If this is a tape drive, the write must be initiated. 29937736Smckusick */ 30048360Smckusick if (VOP_IOCTL(bp->b_vp, 0, (caddr_t)B_TAPE, 0, NOCRED, p) == 0) { 3018Sbill bawrite(bp); 30239668Smckusick } else { 30346151Smckusick bp->b_flags |= (B_DONE | B_DELWRI); 3048Sbill brelse(bp); 3058Sbill } 3068Sbill } 3078Sbill 3088Sbill /* 30946151Smckusick * Asynchronous write. 31046151Smckusick * Start I/O on a buffer, but do not wait for it to complete. 31146151Smckusick * The buffer is released when the I/O completes. 3128Sbill */ 3138Sbill bawrite(bp) 3147015Smckusick register struct buf *bp; 3158Sbill { 3168Sbill 31746151Smckusick /* 31846151Smckusick * Setting the ASYNC flag causes bwrite to return 31946151Smckusick * after starting the I/O. 32046151Smckusick */ 3218Sbill bp->b_flags |= B_ASYNC; 32237736Smckusick (void) bwrite(bp); 3238Sbill } 3248Sbill 3258Sbill /* 32646151Smckusick * Release a buffer. 32746151Smckusick * Even if the buffer is dirty, no I/O is started. 3288Sbill */ 3298Sbill brelse(bp) 3307015Smckusick register struct buf *bp; 3318Sbill { 33256607Smckusick register struct queue_entry *flist; 33346151Smckusick int s; 3348Sbill 33540341Smckusick trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno); 3367015Smckusick /* 33739668Smckusick * If a process is waiting for the buffer, or 33839668Smckusick * is waiting for a free buffer, awaken it. 3397015Smckusick */ 34046151Smckusick if (bp->b_flags & B_WANTED) 3418Sbill wakeup((caddr_t)bp); 34256395Smckusick if (needbuffer) { 34356395Smckusick needbuffer = 0; 34456395Smckusick wakeup((caddr_t)&needbuffer); 3458Sbill } 34639668Smckusick /* 34739668Smckusick * Retry I/O for locked buffers rather than invalidating them. 34839668Smckusick */ 34952413Storek s = splbio(); 35039668Smckusick if ((bp->b_flags & B_ERROR) && (bp->b_flags & B_LOCKED)) 35139668Smckusick bp->b_flags &= ~B_ERROR; 35239668Smckusick /* 35339668Smckusick * Disassociate buffers that are no longer valid. 35439668Smckusick */ 35546151Smckusick if (bp->b_flags & (B_NOCACHE | B_ERROR)) 35637736Smckusick bp->b_flags |= B_INVAL; 35746151Smckusick if ((bp->b_bufsize <= 0) || (bp->b_flags & (B_ERROR | B_INVAL))) { 35839668Smckusick if (bp->b_vp) 35939668Smckusick brelvp(bp); 36039668Smckusick bp->b_flags &= ~B_DELWRI; 36137736Smckusick } 3627015Smckusick /* 3637015Smckusick * Stick the buffer back on a free list. 3647015Smckusick */ 3658670S if (bp->b_bufsize <= 0) { 3668670S /* block has no buffer ... put at front of unused buffer list */ 36756395Smckusick flist = &bufqueues[BQ_EMPTY]; 3688670S binsheadfree(bp, flist); 36946151Smckusick } else if (bp->b_flags & (B_ERROR | B_INVAL)) { 3702325Swnj /* block has no info ... put at front of most free list */ 37156395Smckusick flist = &bufqueues[BQ_AGE]; 3727015Smckusick binsheadfree(bp, flist); 3738Sbill } else { 3742325Swnj if (bp->b_flags & B_LOCKED) 37556395Smckusick flist = &bufqueues[BQ_LOCKED]; 3762325Swnj else if (bp->b_flags & B_AGE) 37756395Smckusick flist = &bufqueues[BQ_AGE]; 3782325Swnj else 37956395Smckusick flist = &bufqueues[BQ_LRU]; 3807015Smckusick binstailfree(bp, flist); 3818Sbill } 38246151Smckusick bp->b_flags &= ~(B_WANTED | B_BUSY | B_ASYNC | B_AGE | B_NOCACHE); 3838Sbill splx(s); 3848Sbill } 3858Sbill 3868Sbill /* 38746151Smckusick * Check to see if a block is currently memory resident. 3888Sbill */ 38937736Smckusick incore(vp, blkno) 39037736Smckusick struct vnode *vp; 3917015Smckusick daddr_t blkno; 3928Sbill { 3938Sbill register struct buf *bp; 3948Sbill 39556607Smckusick for (bp = BUFHASH(vp, blkno)->le_next; bp; bp = bp->b_hash.qe_next) 39639668Smckusick if (bp->b_lblkno == blkno && bp->b_vp == vp && 3977015Smckusick (bp->b_flags & B_INVAL) == 0) 39891Sbill return (1); 39991Sbill return (0); 4008Sbill } 4018Sbill 40239668Smckusick /* 40346151Smckusick * Check to see if a block is currently memory resident. 40446151Smckusick * If it is resident, return it. If it is not resident, 40546151Smckusick * allocate a new buffer and assign it to the block. 40639668Smckusick */ 4078Sbill struct buf * 40837736Smckusick getblk(vp, blkno, size) 40937736Smckusick register struct vnode *vp; 4106563Smckusic daddr_t blkno; 4116563Smckusic int size; 4128Sbill { 41356607Smckusick register struct buf *bp; 41456607Smckusick struct list_entry *dp; 4155424Swnj int s; 4168Sbill 41725255Smckusick if (size > MAXBSIZE) 41825255Smckusick panic("getblk: size too big"); 4197015Smckusick /* 42046151Smckusick * Search the cache for the block. If the buffer is found, 42146151Smckusick * but it is currently locked, the we must wait for it to 42246151Smckusick * become available. 4237015Smckusick */ 42437736Smckusick dp = BUFHASH(vp, blkno); 4257015Smckusick loop: 42656607Smckusick for (bp = dp->le_next; bp; bp = bp->b_hash.qe_next) { 42739668Smckusick if (bp->b_lblkno != blkno || bp->b_vp != vp || 42846151Smckusick (bp->b_flags & B_INVAL)) 4298Sbill continue; 43026271Skarels s = splbio(); 43146151Smckusick if (bp->b_flags & B_BUSY) { 4328Sbill bp->b_flags |= B_WANTED; 43346151Smckusick sleep((caddr_t)bp, PRIBIO + 1); 4345424Swnj splx(s); 4358Sbill goto loop; 4368Sbill } 43739882Smckusick bremfree(bp); 43839882Smckusick bp->b_flags |= B_BUSY; 4395424Swnj splx(s); 44032608Smckusick if (bp->b_bcount != size) { 44139668Smckusick printf("getblk: stray size"); 44239668Smckusick bp->b_flags |= B_INVAL; 44339668Smckusick bwrite(bp); 44439668Smckusick goto loop; 44532608Smckusick } 4468Sbill bp->b_flags |= B_CACHE; 44726271Skarels return (bp); 4488Sbill } 4498670S bp = getnewbuf(); 4507015Smckusick bremhash(bp); 45139668Smckusick bgetvp(vp, bp); 45245116Smckusick bp->b_bcount = 0; 45339668Smckusick bp->b_lblkno = blkno; 4546563Smckusic bp->b_blkno = blkno; 4558670S bp->b_error = 0; 45637736Smckusick bp->b_resid = 0; 45737736Smckusick binshash(bp, dp); 45845116Smckusick allocbuf(bp, size); 45926271Skarels return (bp); 4608Sbill } 4618Sbill 4628Sbill /* 46346151Smckusick * Allocate a buffer. 46446151Smckusick * The caller will assign it to a block. 4658Sbill */ 4668Sbill struct buf * 4676563Smckusic geteblk(size) 4686563Smckusic int size; 4698Sbill { 47056395Smckusick register struct buf *bp; 4718Sbill 47225255Smckusick if (size > MAXBSIZE) 47325255Smckusick panic("geteblk: size too big"); 4748670S bp = getnewbuf(); 4758670S bp->b_flags |= B_INVAL; 4767015Smckusick bremhash(bp); 47756395Smckusick binshash(bp, &invalhash); 47845116Smckusick bp->b_bcount = 0; 47937736Smckusick bp->b_error = 0; 48037736Smckusick bp->b_resid = 0; 48145116Smckusick allocbuf(bp, size); 48226271Skarels return (bp); 4838Sbill } 4848Sbill 4858Sbill /* 48645116Smckusick * Expand or contract the actual memory allocated to a buffer. 48746151Smckusick * If no memory is available, release buffer and take error exit. 4886563Smckusic */ 48945116Smckusick allocbuf(tp, size) 49045116Smckusick register struct buf *tp; 4916563Smckusic int size; 4926563Smckusic { 49345116Smckusick register struct buf *bp, *ep; 49445116Smckusick int sizealloc, take, s; 4956563Smckusic 49645116Smckusick sizealloc = roundup(size, CLBYTES); 49745116Smckusick /* 49845116Smckusick * Buffer size does not change 49945116Smckusick */ 50045116Smckusick if (sizealloc == tp->b_bufsize) 50145116Smckusick goto out; 50245116Smckusick /* 50345116Smckusick * Buffer size is shrinking. 50445116Smckusick * Place excess space in a buffer header taken from the 50545116Smckusick * BQ_EMPTY buffer list and placed on the "most free" list. 50645116Smckusick * If no extra buffer headers are available, leave the 50745116Smckusick * extra space in the present buffer. 50845116Smckusick */ 50945116Smckusick if (sizealloc < tp->b_bufsize) { 51056607Smckusick if ((ep = bufqueues[BQ_EMPTY].qe_next) == NULL) 51145116Smckusick goto out; 51245116Smckusick s = splbio(); 51345116Smckusick bremfree(ep); 51445116Smckusick ep->b_flags |= B_BUSY; 51545116Smckusick splx(s); 51645116Smckusick pagemove(tp->b_un.b_addr + sizealloc, ep->b_un.b_addr, 51745116Smckusick (int)tp->b_bufsize - sizealloc); 51845116Smckusick ep->b_bufsize = tp->b_bufsize - sizealloc; 51945116Smckusick tp->b_bufsize = sizealloc; 52045116Smckusick ep->b_flags |= B_INVAL; 52145116Smckusick ep->b_bcount = 0; 52245116Smckusick brelse(ep); 52345116Smckusick goto out; 52445116Smckusick } 52545116Smckusick /* 52645116Smckusick * More buffer space is needed. Get it out of buffers on 52745116Smckusick * the "most free" list, placing the empty headers on the 52845116Smckusick * BQ_EMPTY buffer header list. 52945116Smckusick */ 53045116Smckusick while (tp->b_bufsize < sizealloc) { 53145116Smckusick take = sizealloc - tp->b_bufsize; 53245116Smckusick bp = getnewbuf(); 53345116Smckusick if (take >= bp->b_bufsize) 53445116Smckusick take = bp->b_bufsize; 53545116Smckusick pagemove(&bp->b_un.b_addr[bp->b_bufsize - take], 53645116Smckusick &tp->b_un.b_addr[tp->b_bufsize], take); 53745116Smckusick tp->b_bufsize += take; 53845116Smckusick bp->b_bufsize = bp->b_bufsize - take; 53945116Smckusick if (bp->b_bcount > bp->b_bufsize) 54045116Smckusick bp->b_bcount = bp->b_bufsize; 54145116Smckusick if (bp->b_bufsize <= 0) { 54245116Smckusick bremhash(bp); 54356395Smckusick binshash(bp, &invalhash); 54446151Smckusick bp->b_dev = NODEV; 54545116Smckusick bp->b_error = 0; 54645116Smckusick bp->b_flags |= B_INVAL; 54745116Smckusick } 54845116Smckusick brelse(bp); 54945116Smckusick } 55045116Smckusick out: 55145116Smckusick tp->b_bcount = size; 55245116Smckusick return (1); 5538670S } 5548670S 5558670S /* 5568670S * Find a buffer which is available for use. 5578670S * Select something from a free list. 5588670S * Preference is to AGE list, then LRU list. 5598670S */ 5608670S struct buf * 5618670S getnewbuf() 5628670S { 56356395Smckusick register struct buf *bp; 56456607Smckusick register struct queue_entry *dp; 56538776Smckusick register struct ucred *cred; 5668670S int s; 5678670S 5688670S loop: 56926271Skarels s = splbio(); 57056395Smckusick for (dp = &bufqueues[BQ_AGE]; dp > bufqueues; dp--) 57156607Smckusick if (dp->qe_next) 5728670S break; 57356395Smckusick if (dp == bufqueues) { /* no free blocks */ 57456395Smckusick needbuffer = 1; 57556395Smckusick sleep((caddr_t)&needbuffer, PRIBIO + 1); 57612170Ssam splx(s); 5778670S goto loop; 5788670S } 57956607Smckusick bp = dp->qe_next; 58039882Smckusick bremfree(bp); 58139882Smckusick bp->b_flags |= B_BUSY; 5828670S splx(s); 5838670S if (bp->b_flags & B_DELWRI) { 58438614Smckusick (void) bawrite(bp); 5858670S goto loop; 5868670S } 58740341Smckusick trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno); 58839668Smckusick if (bp->b_vp) 58939668Smckusick brelvp(bp); 59038776Smckusick if (bp->b_rcred != NOCRED) { 59138776Smckusick cred = bp->b_rcred; 59238776Smckusick bp->b_rcred = NOCRED; 59338776Smckusick crfree(cred); 59438776Smckusick } 59538776Smckusick if (bp->b_wcred != NOCRED) { 59638776Smckusick cred = bp->b_wcred; 59738776Smckusick bp->b_wcred = NOCRED; 59838776Smckusick crfree(cred); 59938776Smckusick } 6008670S bp->b_flags = B_BUSY; 60146989Smckusick bp->b_dirtyoff = bp->b_dirtyend = 0; 60252189Smckusick bp->b_validoff = bp->b_validend = 0; 6038670S return (bp); 6048670S } 6058670S 6068670S /* 60746151Smckusick * Wait for I/O to complete. 60846151Smckusick * 60946151Smckusick * Extract and return any errors associated with the I/O. 61046151Smckusick * If the error flag is set, but no specific error is 61146151Smckusick * given, return EIO. 6128Sbill */ 6137015Smckusick biowait(bp) 6146563Smckusic register struct buf *bp; 6158Sbill { 6165431Sroot int s; 6178Sbill 61826271Skarels s = splbio(); 61938776Smckusick while ((bp->b_flags & B_DONE) == 0) 6208Sbill sleep((caddr_t)bp, PRIBIO); 6215431Sroot splx(s); 62237736Smckusick if ((bp->b_flags & B_ERROR) == 0) 62337736Smckusick return (0); 62437736Smckusick if (bp->b_error) 62537736Smckusick return (bp->b_error); 62637736Smckusick return (EIO); 6278Sbill } 6288Sbill 6298Sbill /* 63013128Ssam * Mark I/O complete on a buffer. 63146151Smckusick * 63246151Smckusick * If a callback has been requested, e.g. the pageout 63346151Smckusick * daemon, do so. Otherwise, awaken waiting processes. 6348Sbill */ 63551455Sbostic void 6367015Smckusick biodone(bp) 6377015Smckusick register struct buf *bp; 6388Sbill { 6398Sbill 640420Sbill if (bp->b_flags & B_DONE) 6417015Smckusick panic("dup biodone"); 6428Sbill bp->b_flags |= B_DONE; 64349232Smckusick if ((bp->b_flags & B_READ) == 0) 64449232Smckusick vwakeup(bp); 6459763Ssam if (bp->b_flags & B_CALL) { 6469763Ssam bp->b_flags &= ~B_CALL; 6479763Ssam (*bp->b_iodone)(bp); 6489763Ssam return; 6499763Ssam } 65046151Smckusick if (bp->b_flags & B_ASYNC) 6518Sbill brelse(bp); 6528Sbill else { 6538Sbill bp->b_flags &= ~B_WANTED; 6548Sbill wakeup((caddr_t)bp); 6558Sbill } 6568Sbill } 65756356Smckusick 658*57035Smargo int 659*57035Smargo count_lock_queue() 660*57035Smargo { 661*57035Smargo register struct buf *bp; 662*57035Smargo register int ret; 663*57035Smargo 664*57035Smargo for (ret = 0, bp = (struct buf *)bufqueues[BQ_LOCKED].qe_next; 665*57035Smargo bp; bp = (struct buf *)bp->b_freelist.qe_next) 666*57035Smargo ++ret; 667*57035Smargo return(ret); 668*57035Smargo } 669*57035Smargo 67056356Smckusick #ifdef DIAGNOSTIC 67156356Smckusick /* 67256356Smckusick * Print out statistics on the current allocation of the buffer pool. 67356356Smckusick * Can be enabled to print out on every ``sync'' by setting "syncprt" 67456356Smckusick * above. 67556356Smckusick */ 67656356Smckusick void 67756356Smckusick vfs_bufstats() 67856356Smckusick { 67956356Smckusick int s, i, j, count; 68056395Smckusick register struct buf *bp; 68156607Smckusick register struct queue_entry *dp; 68256356Smckusick int counts[MAXBSIZE/CLBYTES+1]; 68356356Smckusick static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" }; 68456356Smckusick 68556395Smckusick for (dp = bufqueues, i = 0; dp < &bufqueues[BQUEUES]; dp++, i++) { 68656356Smckusick count = 0; 68756356Smckusick for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 68856356Smckusick counts[j] = 0; 68956356Smckusick s = splbio(); 69056607Smckusick for (bp = dp->qe_next; bp; bp = bp->b_freelist.qe_next) { 69156356Smckusick counts[bp->b_bufsize/CLBYTES]++; 69256356Smckusick count++; 69356356Smckusick } 69456356Smckusick splx(s); 69556356Smckusick printf("%s: total-%d", bname[i], count); 69656356Smckusick for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 69756356Smckusick if (counts[j] != 0) 69856356Smckusick printf(", %d-%d", j * CLBYTES, counts[j]); 69956356Smckusick printf("\n"); 70056356Smckusick } 70156356Smckusick } 70256356Smckusick #endif /* DIAGNOSTIC */ 703