xref: /csrg-svn/sys/kern/vfs_cluster.c (revision 52189)
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*52189Smckusick  *	@(#)vfs_cluster.c	7.45 (Berkeley) 01/14/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/specdev.h>
1751455Sbostic #include <sys/mount.h>
1851455Sbostic #include <sys/trace.h>
1951455Sbostic #include <sys/resourcevar.h>
208Sbill 
2191Sbill /*
2249280Skarels  * Initialize buffers and hash links for buffers.
2349280Skarels  */
2451455Sbostic void
2549280Skarels bufinit()
2649280Skarels {
2749280Skarels 	register int i;
2849280Skarels 	register struct buf *bp, *dp;
2949280Skarels 	register struct bufhd *hp;
3049280Skarels 	int base, residual;
3149280Skarels 
3249280Skarels 	for (hp = bufhash, i = 0; i < BUFHSZ; i++, hp++)
3349280Skarels 		hp->b_forw = hp->b_back = (struct buf *)hp;
3449280Skarels 
3549280Skarels 	for (dp = bfreelist; dp < &bfreelist[BQUEUES]; dp++) {
3649280Skarels 		dp->b_forw = dp->b_back = dp->av_forw = dp->av_back = dp;
3749280Skarels 		dp->b_flags = B_HEAD;
3849280Skarels 	}
3949280Skarels 	base = bufpages / nbuf;
4049280Skarels 	residual = bufpages % nbuf;
4149280Skarels 	for (i = 0; i < nbuf; i++) {
4249280Skarels 		bp = &buf[i];
4349280Skarels 		bp->b_dev = NODEV;
4449280Skarels 		bp->b_bcount = 0;
4549280Skarels 		bp->b_rcred = NOCRED;
4649280Skarels 		bp->b_wcred = NOCRED;
4749280Skarels 		bp->b_dirtyoff = 0;
4849280Skarels 		bp->b_dirtyend = 0;
49*52189Smckusick 		bp->b_validoff = 0;
50*52189Smckusick 		bp->b_validend = 0;
5149280Skarels 		bp->b_un.b_addr = buffers + i * MAXBSIZE;
5249280Skarels 		if (i < residual)
5349280Skarels 			bp->b_bufsize = (base + 1) * CLBYTES;
5449280Skarels 		else
5549280Skarels 			bp->b_bufsize = base * CLBYTES;
5649280Skarels 		binshash(bp, &bfreelist[BQ_AGE]);
5749280Skarels 		bp->b_flags = B_BUSY|B_INVAL;
5849280Skarels 		brelse(bp);
5949280Skarels 	}
6049280Skarels }
6149280Skarels 
6249280Skarels /*
6346151Smckusick  * Find the block in the buffer pool.
6446151Smckusick  * If the buffer is not present, allocate a new buffer and load
6546151Smckusick  * its contents according to the filesystem fill routine.
668Sbill  */
6738776Smckusick bread(vp, blkno, size, cred, bpp)
6837736Smckusick 	struct vnode *vp;
696563Smckusic 	daddr_t blkno;
706563Smckusic 	int size;
7138776Smckusick 	struct ucred *cred;
7237736Smckusick 	struct buf **bpp;
738Sbill {
7447545Skarels 	struct proc *p = curproc;		/* XXX */
758Sbill 	register struct buf *bp;
768Sbill 
778670S 	if (size == 0)
788670S 		panic("bread: size 0");
7937736Smckusick 	*bpp = bp = getblk(vp, blkno, size);
8046151Smckusick 	if (bp->b_flags & (B_DONE | B_DELWRI)) {
8140341Smckusick 		trace(TR_BREADHIT, pack(vp, size), blkno);
8237736Smckusick 		return (0);
838Sbill 	}
848Sbill 	bp->b_flags |= B_READ;
858670S 	if (bp->b_bcount > bp->b_bufsize)
868670S 		panic("bread");
8738776Smckusick 	if (bp->b_rcred == NOCRED && cred != NOCRED) {
8838776Smckusick 		crhold(cred);
8938776Smckusick 		bp->b_rcred = cred;
9038776Smckusick 	}
9137736Smckusick 	VOP_STRATEGY(bp);
9240341Smckusick 	trace(TR_BREADMISS, pack(vp, size), blkno);
9347545Skarels 	p->p_stats->p_ru.ru_inblock++;		/* pay for read */
9437736Smckusick 	return (biowait(bp));
958Sbill }
968Sbill 
978Sbill /*
98*52189Smckusick  * Operates like bread, but also starts I/O on the N specified
99*52189Smckusick  * read-ahead blocks.
1008Sbill  */
101*52189Smckusick breadn(vp, blkno, size, rablkno, rabsize, num, cred, bpp)
10237736Smckusick 	struct vnode *vp;
1037114Smckusick 	daddr_t blkno; int size;
104*52189Smckusick 	daddr_t rablkno[]; int rabsize[];
105*52189Smckusick 	int num;
10638776Smckusick 	struct ucred *cred;
10737736Smckusick 	struct buf **bpp;
1088Sbill {
10947545Skarels 	struct proc *p = curproc;		/* XXX */
1108Sbill 	register struct buf *bp, *rabp;
111*52189Smckusick 	register int i;
1128Sbill 
1138Sbill 	bp = NULL;
1147015Smckusick 	/*
11546151Smckusick 	 * If the block is not memory resident,
11646151Smckusick 	 * allocate a buffer and start I/O.
1177015Smckusick 	 */
11837736Smckusick 	if (!incore(vp, blkno)) {
11937736Smckusick 		*bpp = bp = getblk(vp, blkno, size);
12046151Smckusick 		if ((bp->b_flags & (B_DONE | B_DELWRI)) == 0) {
1218Sbill 			bp->b_flags |= B_READ;
1228670S 			if (bp->b_bcount > bp->b_bufsize)
123*52189Smckusick 				panic("breadn");
12438776Smckusick 			if (bp->b_rcred == NOCRED && cred != NOCRED) {
12538776Smckusick 				crhold(cred);
12638776Smckusick 				bp->b_rcred = cred;
12738776Smckusick 			}
12837736Smckusick 			VOP_STRATEGY(bp);
12940341Smckusick 			trace(TR_BREADMISS, pack(vp, size), blkno);
13047545Skarels 			p->p_stats->p_ru.ru_inblock++;	/* pay for read */
1317015Smckusick 		} else
13240341Smckusick 			trace(TR_BREADHIT, pack(vp, size), blkno);
1338Sbill 	}
1347015Smckusick 
1357015Smckusick 	/*
136*52189Smckusick 	 * If there's read-ahead block(s), start I/O
137*52189Smckusick 	 * on them also (as above).
1387015Smckusick 	 */
139*52189Smckusick 	for (i = 0; i < num; i++) {
140*52189Smckusick 		if (incore(vp, rablkno[i]))
141*52189Smckusick 			continue;
142*52189Smckusick 		rabp = getblk(vp, rablkno[i], rabsize[i]);
14346151Smckusick 		if (rabp->b_flags & (B_DONE | B_DELWRI)) {
1448Sbill 			brelse(rabp);
145*52189Smckusick 			trace(TR_BREADHITRA, pack(vp, rabsize[i]), rablkno[i]);
1462045Swnj 		} else {
14746151Smckusick 			rabp->b_flags |= B_ASYNC | B_READ;
1488670S 			if (rabp->b_bcount > rabp->b_bufsize)
1498670S 				panic("breadrabp");
15038880Smckusick 			if (rabp->b_rcred == NOCRED && cred != NOCRED) {
15138776Smckusick 				crhold(cred);
15238880Smckusick 				rabp->b_rcred = cred;
15338776Smckusick 			}
15437736Smckusick 			VOP_STRATEGY(rabp);
155*52189Smckusick 			trace(TR_BREADMISSRA, pack(vp, rabsize[i]), rablkno[i]);
15647545Skarels 			p->p_stats->p_ru.ru_inblock++;	/* pay in advance */
1578Sbill 		}
1588Sbill 	}
1597015Smckusick 
1607015Smckusick 	/*
16146151Smckusick 	 * If block was memory resident, let bread get it.
16246151Smckusick 	 * If block was not memory resident, the read was
16346151Smckusick 	 * started above, so just wait for the read to complete.
1647015Smckusick 	 */
1657114Smckusick 	if (bp == NULL)
16638776Smckusick 		return (bread(vp, blkno, size, cred, bpp));
16737736Smckusick 	return (biowait(bp));
1688Sbill }
1698Sbill 
1708Sbill /*
17146151Smckusick  * Synchronous write.
17246151Smckusick  * Release buffer on completion.
1738Sbill  */
1748Sbill bwrite(bp)
1757015Smckusick 	register struct buf *bp;
1768Sbill {
17747545Skarels 	struct proc *p = curproc;		/* XXX */
17837736Smckusick 	register int flag;
17940226Smckusick 	int s, error;
1808Sbill 
1818Sbill 	flag = bp->b_flags;
1829857Ssam 	bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI);
18349459Smckusick 	if (flag & B_ASYNC) {
18449459Smckusick 		if ((flag & B_DELWRI) == 0)
18549459Smckusick 			p->p_stats->p_ru.ru_oublock++;	/* no one paid yet */
18649459Smckusick 		else
18749459Smckusick 			reassignbuf(bp, bp->b_vp);
18849459Smckusick 	}
18940341Smckusick 	trace(TR_BWRITE, pack(bp->b_vp, bp->b_bcount), bp->b_lblkno);
1908670S 	if (bp->b_bcount > bp->b_bufsize)
1918670S 		panic("bwrite");
19240226Smckusick 	s = splbio();
19339882Smckusick 	bp->b_vp->v_numoutput++;
19440226Smckusick 	splx(s);
19537736Smckusick 	VOP_STRATEGY(bp);
1967015Smckusick 
1977015Smckusick 	/*
19846151Smckusick 	 * If the write was synchronous, then await I/O completion.
1997015Smckusick 	 * If the write was "delayed", then we put the buffer on
20046151Smckusick 	 * the queue of blocks awaiting I/O completion status.
2017015Smckusick 	 */
20246151Smckusick 	if ((flag & B_ASYNC) == 0) {
20337736Smckusick 		error = biowait(bp);
20449459Smckusick 		if ((flag&B_DELWRI) == 0)
20549459Smckusick 			p->p_stats->p_ru.ru_oublock++;	/* no one paid yet */
20649459Smckusick 		else
20749459Smckusick 			reassignbuf(bp, bp->b_vp);
2088Sbill 		brelse(bp);
20937736Smckusick 	} else if (flag & B_DELWRI) {
2108Sbill 		bp->b_flags |= B_AGE;
21137736Smckusick 		error = 0;
21237736Smckusick 	}
21337736Smckusick 	return (error);
2148Sbill }
2158Sbill 
2168Sbill /*
21746151Smckusick  * Delayed write.
21846151Smckusick  *
21946151Smckusick  * The buffer is marked dirty, but is not queued for I/O.
22046151Smckusick  * This routine should be used when the buffer is expected
22146151Smckusick  * to be modified again soon, typically a small write that
22246151Smckusick  * partially fills a buffer.
22346151Smckusick  *
22446151Smckusick  * NB: magnetic tapes cannot be delayed; they must be
22546151Smckusick  * written in the order that the writes are requested.
2268Sbill  */
2278Sbill bdwrite(bp)
2287015Smckusick 	register struct buf *bp;
2298Sbill {
23047545Skarels 	struct proc *p = curproc;		/* XXX */
2318Sbill 
23239882Smckusick 	if ((bp->b_flags & B_DELWRI) == 0) {
23339882Smckusick 		bp->b_flags |= B_DELWRI;
23439882Smckusick 		reassignbuf(bp, bp->b_vp);
23547545Skarels 		p->p_stats->p_ru.ru_oublock++;		/* no one paid yet */
23639882Smckusick 	}
23737736Smckusick 	/*
23839668Smckusick 	 * If this is a tape drive, the write must be initiated.
23937736Smckusick 	 */
24048360Smckusick 	if (VOP_IOCTL(bp->b_vp, 0, (caddr_t)B_TAPE, 0, NOCRED, p) == 0) {
2418Sbill 		bawrite(bp);
24239668Smckusick 	} else {
24346151Smckusick 		bp->b_flags |= (B_DONE | B_DELWRI);
2448Sbill 		brelse(bp);
2458Sbill 	}
2468Sbill }
2478Sbill 
2488Sbill /*
24946151Smckusick  * Asynchronous write.
25046151Smckusick  * Start I/O on a buffer, but do not wait for it to complete.
25146151Smckusick  * The buffer is released when the I/O completes.
2528Sbill  */
2538Sbill bawrite(bp)
2547015Smckusick 	register struct buf *bp;
2558Sbill {
2568Sbill 
25746151Smckusick 	/*
25846151Smckusick 	 * Setting the ASYNC flag causes bwrite to return
25946151Smckusick 	 * after starting the I/O.
26046151Smckusick 	 */
2618Sbill 	bp->b_flags |= B_ASYNC;
26237736Smckusick 	(void) bwrite(bp);
2638Sbill }
2648Sbill 
2658Sbill /*
26646151Smckusick  * Release a buffer.
26746151Smckusick  * Even if the buffer is dirty, no I/O is started.
2688Sbill  */
2698Sbill brelse(bp)
2707015Smckusick 	register struct buf *bp;
2718Sbill {
2722325Swnj 	register struct buf *flist;
27346151Smckusick 	int s;
2748Sbill 
27540341Smckusick 	trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno);
2767015Smckusick 	/*
27739668Smckusick 	 * If a process is waiting for the buffer, or
27839668Smckusick 	 * is waiting for a free buffer, awaken it.
2797015Smckusick 	 */
28046151Smckusick 	if (bp->b_flags & B_WANTED)
2818Sbill 		wakeup((caddr_t)bp);
28246151Smckusick 	if (bfreelist[0].b_flags & B_WANTED) {
2832325Swnj 		bfreelist[0].b_flags &= ~B_WANTED;
2842325Swnj 		wakeup((caddr_t)bfreelist);
2858Sbill 	}
28639668Smckusick 	/*
28739668Smckusick 	 * Retry I/O for locked buffers rather than invalidating them.
28839668Smckusick 	 */
28939668Smckusick 	if ((bp->b_flags & B_ERROR) && (bp->b_flags & B_LOCKED))
29039668Smckusick 		bp->b_flags &= ~B_ERROR;
29139668Smckusick 	/*
29239668Smckusick 	 * Disassociate buffers that are no longer valid.
29339668Smckusick 	 */
29446151Smckusick 	if (bp->b_flags & (B_NOCACHE | B_ERROR))
29537736Smckusick 		bp->b_flags |= B_INVAL;
29646151Smckusick 	if ((bp->b_bufsize <= 0) || (bp->b_flags & (B_ERROR | B_INVAL))) {
29739668Smckusick 		if (bp->b_vp)
29839668Smckusick 			brelvp(bp);
29939668Smckusick 		bp->b_flags &= ~B_DELWRI;
30037736Smckusick 	}
3017015Smckusick 	/*
3027015Smckusick 	 * Stick the buffer back on a free list.
3037015Smckusick 	 */
30426271Skarels 	s = splbio();
3058670S 	if (bp->b_bufsize <= 0) {
3068670S 		/* block has no buffer ... put at front of unused buffer list */
3078670S 		flist = &bfreelist[BQ_EMPTY];
3088670S 		binsheadfree(bp, flist);
30946151Smckusick 	} else if (bp->b_flags & (B_ERROR | B_INVAL)) {
3102325Swnj 		/* block has no info ... put at front of most free list */
3118670S 		flist = &bfreelist[BQ_AGE];
3127015Smckusick 		binsheadfree(bp, flist);
3138Sbill 	} else {
3142325Swnj 		if (bp->b_flags & B_LOCKED)
3152325Swnj 			flist = &bfreelist[BQ_LOCKED];
3162325Swnj 		else if (bp->b_flags & B_AGE)
3172325Swnj 			flist = &bfreelist[BQ_AGE];
3182325Swnj 		else
3192325Swnj 			flist = &bfreelist[BQ_LRU];
3207015Smckusick 		binstailfree(bp, flist);
3218Sbill 	}
32246151Smckusick 	bp->b_flags &= ~(B_WANTED | B_BUSY | B_ASYNC | B_AGE | B_NOCACHE);
3238Sbill 	splx(s);
3248Sbill }
3258Sbill 
3268Sbill /*
32746151Smckusick  * Check to see if a block is currently memory resident.
3288Sbill  */
32937736Smckusick incore(vp, blkno)
33037736Smckusick 	struct vnode *vp;
3317015Smckusick 	daddr_t blkno;
3328Sbill {
3338Sbill 	register struct buf *bp;
3342325Swnj 	register struct buf *dp;
3358Sbill 
33638225Smckusick 	dp = BUFHASH(vp, blkno);
3372325Swnj 	for (bp = dp->b_forw; bp != dp; bp = bp->b_forw)
33839668Smckusick 		if (bp->b_lblkno == blkno && bp->b_vp == vp &&
3397015Smckusick 		    (bp->b_flags & B_INVAL) == 0)
34091Sbill 			return (1);
34191Sbill 	return (0);
3428Sbill }
3438Sbill 
34439668Smckusick /*
34546151Smckusick  * Check to see if a block is currently memory resident.
34646151Smckusick  * If it is resident, return it. If it is not resident,
34746151Smckusick  * allocate a new buffer and assign it to the block.
34839668Smckusick  */
3498Sbill struct buf *
35037736Smckusick getblk(vp, blkno, size)
35137736Smckusick 	register struct vnode *vp;
3526563Smckusic 	daddr_t blkno;
3536563Smckusic 	int size;
3548Sbill {
3558670S 	register struct buf *bp, *dp;
3565424Swnj 	int s;
3578Sbill 
35825255Smckusick 	if (size > MAXBSIZE)
35925255Smckusick 		panic("getblk: size too big");
3607015Smckusick 	/*
36146151Smckusick 	 * Search the cache for the block. If the buffer is found,
36246151Smckusick 	 * but it is currently locked, the we must wait for it to
36346151Smckusick 	 * become available.
3647015Smckusick 	 */
36537736Smckusick 	dp = BUFHASH(vp, blkno);
3667015Smckusick loop:
3672325Swnj 	for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) {
36839668Smckusick 		if (bp->b_lblkno != blkno || bp->b_vp != vp ||
36946151Smckusick 		    (bp->b_flags & B_INVAL))
3708Sbill 			continue;
37126271Skarels 		s = splbio();
37246151Smckusick 		if (bp->b_flags & B_BUSY) {
3738Sbill 			bp->b_flags |= B_WANTED;
37446151Smckusick 			sleep((caddr_t)bp, PRIBIO + 1);
3755424Swnj 			splx(s);
3768Sbill 			goto loop;
3778Sbill 		}
37839882Smckusick 		bremfree(bp);
37939882Smckusick 		bp->b_flags |= B_BUSY;
3805424Swnj 		splx(s);
38132608Smckusick 		if (bp->b_bcount != size) {
38239668Smckusick 			printf("getblk: stray size");
38339668Smckusick 			bp->b_flags |= B_INVAL;
38439668Smckusick 			bwrite(bp);
38539668Smckusick 			goto loop;
38632608Smckusick 		}
3878Sbill 		bp->b_flags |= B_CACHE;
38826271Skarels 		return (bp);
3898Sbill 	}
3908670S 	bp = getnewbuf();
3917015Smckusick 	bremhash(bp);
39239668Smckusick 	bgetvp(vp, bp);
39345116Smckusick 	bp->b_bcount = 0;
39439668Smckusick 	bp->b_lblkno = blkno;
3956563Smckusic 	bp->b_blkno = blkno;
3968670S 	bp->b_error = 0;
39737736Smckusick 	bp->b_resid = 0;
39837736Smckusick 	binshash(bp, dp);
39945116Smckusick 	allocbuf(bp, size);
40026271Skarels 	return (bp);
4018Sbill }
4028Sbill 
4038Sbill /*
40446151Smckusick  * Allocate a buffer.
40546151Smckusick  * The caller will assign it to a block.
4068Sbill  */
4078Sbill struct buf *
4086563Smckusic geteblk(size)
4096563Smckusic 	int size;
4108Sbill {
4118670S 	register struct buf *bp, *flist;
4128Sbill 
41325255Smckusick 	if (size > MAXBSIZE)
41425255Smckusick 		panic("geteblk: size too big");
4158670S 	bp = getnewbuf();
4168670S 	bp->b_flags |= B_INVAL;
4177015Smckusick 	bremhash(bp);
4188670S 	flist = &bfreelist[BQ_AGE];
41945116Smckusick 	bp->b_bcount = 0;
42037736Smckusick 	bp->b_error = 0;
42137736Smckusick 	bp->b_resid = 0;
4228670S 	binshash(bp, flist);
42345116Smckusick 	allocbuf(bp, size);
42426271Skarels 	return (bp);
4258Sbill }
4268Sbill 
4278Sbill /*
42845116Smckusick  * Expand or contract the actual memory allocated to a buffer.
42946151Smckusick  * If no memory is available, release buffer and take error exit.
4306563Smckusic  */
43145116Smckusick allocbuf(tp, size)
43245116Smckusick 	register struct buf *tp;
4336563Smckusic 	int size;
4346563Smckusic {
43545116Smckusick 	register struct buf *bp, *ep;
43645116Smckusick 	int sizealloc, take, s;
4376563Smckusic 
43845116Smckusick 	sizealloc = roundup(size, CLBYTES);
43945116Smckusick 	/*
44045116Smckusick 	 * Buffer size does not change
44145116Smckusick 	 */
44245116Smckusick 	if (sizealloc == tp->b_bufsize)
44345116Smckusick 		goto out;
44445116Smckusick 	/*
44545116Smckusick 	 * Buffer size is shrinking.
44645116Smckusick 	 * Place excess space in a buffer header taken from the
44745116Smckusick 	 * BQ_EMPTY buffer list and placed on the "most free" list.
44845116Smckusick 	 * If no extra buffer headers are available, leave the
44945116Smckusick 	 * extra space in the present buffer.
45045116Smckusick 	 */
45145116Smckusick 	if (sizealloc < tp->b_bufsize) {
45245116Smckusick 		ep = bfreelist[BQ_EMPTY].av_forw;
45345116Smckusick 		if (ep == &bfreelist[BQ_EMPTY])
45445116Smckusick 			goto out;
45545116Smckusick 		s = splbio();
45645116Smckusick 		bremfree(ep);
45745116Smckusick 		ep->b_flags |= B_BUSY;
45845116Smckusick 		splx(s);
45945116Smckusick 		pagemove(tp->b_un.b_addr + sizealloc, ep->b_un.b_addr,
46045116Smckusick 		    (int)tp->b_bufsize - sizealloc);
46145116Smckusick 		ep->b_bufsize = tp->b_bufsize - sizealloc;
46245116Smckusick 		tp->b_bufsize = sizealloc;
46345116Smckusick 		ep->b_flags |= B_INVAL;
46445116Smckusick 		ep->b_bcount = 0;
46545116Smckusick 		brelse(ep);
46645116Smckusick 		goto out;
46745116Smckusick 	}
46845116Smckusick 	/*
46945116Smckusick 	 * More buffer space is needed. Get it out of buffers on
47045116Smckusick 	 * the "most free" list, placing the empty headers on the
47145116Smckusick 	 * BQ_EMPTY buffer header list.
47245116Smckusick 	 */
47345116Smckusick 	while (tp->b_bufsize < sizealloc) {
47445116Smckusick 		take = sizealloc - tp->b_bufsize;
47545116Smckusick 		bp = getnewbuf();
47645116Smckusick 		if (take >= bp->b_bufsize)
47745116Smckusick 			take = bp->b_bufsize;
47845116Smckusick 		pagemove(&bp->b_un.b_addr[bp->b_bufsize - take],
47945116Smckusick 		    &tp->b_un.b_addr[tp->b_bufsize], take);
48045116Smckusick 		tp->b_bufsize += take;
48145116Smckusick 		bp->b_bufsize = bp->b_bufsize - take;
48245116Smckusick 		if (bp->b_bcount > bp->b_bufsize)
48345116Smckusick 			bp->b_bcount = bp->b_bufsize;
48445116Smckusick 		if (bp->b_bufsize <= 0) {
48545116Smckusick 			bremhash(bp);
48645116Smckusick 			binshash(bp, &bfreelist[BQ_EMPTY]);
48746151Smckusick 			bp->b_dev = NODEV;
48845116Smckusick 			bp->b_error = 0;
48945116Smckusick 			bp->b_flags |= B_INVAL;
49045116Smckusick 		}
49145116Smckusick 		brelse(bp);
49245116Smckusick 	}
49345116Smckusick out:
49445116Smckusick 	tp->b_bcount = size;
49545116Smckusick 	return (1);
4968670S }
4978670S 
4988670S /*
4998670S  * Find a buffer which is available for use.
5008670S  * Select something from a free list.
5018670S  * Preference is to AGE list, then LRU list.
5028670S  */
5038670S struct buf *
5048670S getnewbuf()
5058670S {
5068670S 	register struct buf *bp, *dp;
50738776Smckusick 	register struct ucred *cred;
5088670S 	int s;
5098670S 
51052096Sbostic #ifdef LFS
51152096Sbostic 	lfs_flush();
51252096Sbostic #endif
5138670S loop:
51426271Skarels 	s = splbio();
5158670S 	for (dp = &bfreelist[BQ_AGE]; dp > bfreelist; dp--)
5168670S 		if (dp->av_forw != dp)
5178670S 			break;
5188670S 	if (dp == bfreelist) {		/* no free blocks */
5198670S 		dp->b_flags |= B_WANTED;
52046151Smckusick 		sleep((caddr_t)dp, PRIBIO + 1);
52112170Ssam 		splx(s);
5228670S 		goto loop;
5238670S 	}
52439882Smckusick 	bp = dp->av_forw;
52539882Smckusick 	bremfree(bp);
52639882Smckusick 	bp->b_flags |= B_BUSY;
5278670S 	splx(s);
5288670S 	if (bp->b_flags & B_DELWRI) {
52938614Smckusick 		(void) bawrite(bp);
5308670S 		goto loop;
5318670S 	}
53240341Smckusick 	trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno);
53339668Smckusick 	if (bp->b_vp)
53439668Smckusick 		brelvp(bp);
53538776Smckusick 	if (bp->b_rcred != NOCRED) {
53638776Smckusick 		cred = bp->b_rcred;
53738776Smckusick 		bp->b_rcred = NOCRED;
53838776Smckusick 		crfree(cred);
53938776Smckusick 	}
54038776Smckusick 	if (bp->b_wcred != NOCRED) {
54138776Smckusick 		cred = bp->b_wcred;
54238776Smckusick 		bp->b_wcred = NOCRED;
54338776Smckusick 		crfree(cred);
54438776Smckusick 	}
5458670S 	bp->b_flags = B_BUSY;
54646989Smckusick 	bp->b_dirtyoff = bp->b_dirtyend = 0;
547*52189Smckusick 	bp->b_validoff = bp->b_validend = 0;
5488670S 	return (bp);
5498670S }
5508670S 
5518670S /*
55246151Smckusick  * Wait for I/O to complete.
55346151Smckusick  *
55446151Smckusick  * Extract and return any errors associated with the I/O.
55546151Smckusick  * If the error flag is set, but no specific error is
55646151Smckusick  * given, return EIO.
5578Sbill  */
5587015Smckusick biowait(bp)
5596563Smckusic 	register struct buf *bp;
5608Sbill {
5615431Sroot 	int s;
5628Sbill 
56326271Skarels 	s = splbio();
56438776Smckusick 	while ((bp->b_flags & B_DONE) == 0)
5658Sbill 		sleep((caddr_t)bp, PRIBIO);
5665431Sroot 	splx(s);
56737736Smckusick 	if ((bp->b_flags & B_ERROR) == 0)
56837736Smckusick 		return (0);
56937736Smckusick 	if (bp->b_error)
57037736Smckusick 		return (bp->b_error);
57137736Smckusick 	return (EIO);
5728Sbill }
5738Sbill 
5748Sbill /*
57513128Ssam  * Mark I/O complete on a buffer.
57646151Smckusick  *
57746151Smckusick  * If a callback has been requested, e.g. the pageout
57846151Smckusick  * daemon, do so. Otherwise, awaken waiting processes.
5798Sbill  */
58051455Sbostic void
5817015Smckusick biodone(bp)
5827015Smckusick 	register struct buf *bp;
5838Sbill {
5848Sbill 
585420Sbill 	if (bp->b_flags & B_DONE)
5867015Smckusick 		panic("dup biodone");
5878Sbill 	bp->b_flags |= B_DONE;
58849232Smckusick 	if ((bp->b_flags & B_READ) == 0)
58949232Smckusick 		vwakeup(bp);
5909763Ssam 	if (bp->b_flags & B_CALL) {
5919763Ssam 		bp->b_flags &= ~B_CALL;
5929763Ssam 		(*bp->b_iodone)(bp);
5939763Ssam 		return;
5949763Ssam 	}
59546151Smckusick 	if (bp->b_flags & B_ASYNC)
5968Sbill 		brelse(bp);
5978Sbill 	else {
5988Sbill 		bp->b_flags &= ~B_WANTED;
5998Sbill 		wakeup((caddr_t)bp);
6008Sbill 	}
6018Sbill }
602