xref: /csrg-svn/sys/kern/vfs_cluster.c (revision 49280)
123395Smckusick /*
237736Smckusick  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
337736Smckusick  * All rights reserved.
423395Smckusick  *
544454Sbostic  * %sccs.include.redist.c%
637736Smckusick  *
7*49280Skarels  *	@(#)vfs_cluster.c	7.39 (Berkeley) 05/07/91
823395Smckusick  */
98Sbill 
1017098Sbloom #include "param.h"
1147545Skarels #include "proc.h"
1217098Sbloom #include "buf.h"
1337736Smckusick #include "vnode.h"
1440652Smckusick #include "specdev.h"
1539668Smckusick #include "mount.h"
1617098Sbloom #include "trace.h"
1747568Skarels #include "resourcevar.h"
188Sbill 
1991Sbill /*
20*49280Skarels  * Initialize buffers and hash links for buffers.
21*49280Skarels  */
22*49280Skarels bufinit()
23*49280Skarels {
24*49280Skarels 	register int i;
25*49280Skarels 	register struct buf *bp, *dp;
26*49280Skarels 	register struct bufhd *hp;
27*49280Skarels 	int base, residual;
28*49280Skarels 
29*49280Skarels 	for (hp = bufhash, i = 0; i < BUFHSZ; i++, hp++)
30*49280Skarels 		hp->b_forw = hp->b_back = (struct buf *)hp;
31*49280Skarels 
32*49280Skarels 	for (dp = bfreelist; dp < &bfreelist[BQUEUES]; dp++) {
33*49280Skarels 		dp->b_forw = dp->b_back = dp->av_forw = dp->av_back = dp;
34*49280Skarels 		dp->b_flags = B_HEAD;
35*49280Skarels 	}
36*49280Skarels 	base = bufpages / nbuf;
37*49280Skarels 	residual = bufpages % nbuf;
38*49280Skarels 	for (i = 0; i < nbuf; i++) {
39*49280Skarels 		bp = &buf[i];
40*49280Skarels 		bp->b_dev = NODEV;
41*49280Skarels 		bp->b_bcount = 0;
42*49280Skarels 		bp->b_rcred = NOCRED;
43*49280Skarels 		bp->b_wcred = NOCRED;
44*49280Skarels 		bp->b_dirtyoff = 0;
45*49280Skarels 		bp->b_dirtyend = 0;
46*49280Skarels 		bp->b_un.b_addr = buffers + i * MAXBSIZE;
47*49280Skarels 		if (i < residual)
48*49280Skarels 			bp->b_bufsize = (base + 1) * CLBYTES;
49*49280Skarels 		else
50*49280Skarels 			bp->b_bufsize = base * CLBYTES;
51*49280Skarels 		binshash(bp, &bfreelist[BQ_AGE]);
52*49280Skarels 		bp->b_flags = B_BUSY|B_INVAL;
53*49280Skarels 		brelse(bp);
54*49280Skarels 	}
55*49280Skarels }
56*49280Skarels 
57*49280Skarels /*
5846151Smckusick  * Find the block in the buffer pool.
5946151Smckusick  * If the buffer is not present, allocate a new buffer and load
6046151Smckusick  * its contents according to the filesystem fill routine.
618Sbill  */
6238776Smckusick bread(vp, blkno, size, cred, bpp)
6337736Smckusick 	struct vnode *vp;
646563Smckusic 	daddr_t blkno;
656563Smckusic 	int size;
6638776Smckusick 	struct ucred *cred;
6737736Smckusick 	struct buf **bpp;
688Sbill {
6947545Skarels 	struct proc *p = curproc;		/* XXX */
708Sbill 	register struct buf *bp;
718Sbill 
728670S 	if (size == 0)
738670S 		panic("bread: size 0");
7437736Smckusick 	*bpp = bp = getblk(vp, blkno, size);
7546151Smckusick 	if (bp->b_flags & (B_DONE | B_DELWRI)) {
7640341Smckusick 		trace(TR_BREADHIT, pack(vp, size), blkno);
7737736Smckusick 		return (0);
788Sbill 	}
798Sbill 	bp->b_flags |= B_READ;
808670S 	if (bp->b_bcount > bp->b_bufsize)
818670S 		panic("bread");
8238776Smckusick 	if (bp->b_rcred == NOCRED && cred != NOCRED) {
8338776Smckusick 		crhold(cred);
8438776Smckusick 		bp->b_rcred = cred;
8538776Smckusick 	}
8637736Smckusick 	VOP_STRATEGY(bp);
8740341Smckusick 	trace(TR_BREADMISS, pack(vp, size), blkno);
8847545Skarels 	p->p_stats->p_ru.ru_inblock++;		/* pay for read */
8937736Smckusick 	return (biowait(bp));
908Sbill }
918Sbill 
928Sbill /*
9346151Smckusick  * Operates like bread, but also starts I/O on the specified
9446151Smckusick  * read-ahead block.
958Sbill  */
9638776Smckusick breada(vp, blkno, size, rablkno, rabsize, cred, bpp)
9737736Smckusick 	struct vnode *vp;
987114Smckusick 	daddr_t blkno; int size;
998592Sroot 	daddr_t rablkno; int rabsize;
10038776Smckusick 	struct ucred *cred;
10137736Smckusick 	struct buf **bpp;
1028Sbill {
10347545Skarels 	struct proc *p = curproc;		/* XXX */
1048Sbill 	register struct buf *bp, *rabp;
1058Sbill 
1068Sbill 	bp = NULL;
1077015Smckusick 	/*
10846151Smckusick 	 * If the block is not memory resident,
10946151Smckusick 	 * allocate a buffer and start I/O.
1107015Smckusick 	 */
11137736Smckusick 	if (!incore(vp, blkno)) {
11237736Smckusick 		*bpp = bp = getblk(vp, blkno, size);
11346151Smckusick 		if ((bp->b_flags & (B_DONE | B_DELWRI)) == 0) {
1148Sbill 			bp->b_flags |= B_READ;
1158670S 			if (bp->b_bcount > bp->b_bufsize)
1168670S 				panic("breada");
11738776Smckusick 			if (bp->b_rcred == NOCRED && cred != NOCRED) {
11838776Smckusick 				crhold(cred);
11938776Smckusick 				bp->b_rcred = cred;
12038776Smckusick 			}
12137736Smckusick 			VOP_STRATEGY(bp);
12240341Smckusick 			trace(TR_BREADMISS, pack(vp, size), blkno);
12347545Skarels 			p->p_stats->p_ru.ru_inblock++;	/* pay for read */
1247015Smckusick 		} else
12540341Smckusick 			trace(TR_BREADHIT, pack(vp, size), blkno);
1268Sbill 	}
1277015Smckusick 
1287015Smckusick 	/*
12946151Smckusick 	 * If there is a read-ahead block, start I/O on it too.
1307015Smckusick 	 */
13139895Smckusick 	if (!incore(vp, rablkno)) {
13237736Smckusick 		rabp = getblk(vp, rablkno, rabsize);
13346151Smckusick 		if (rabp->b_flags & (B_DONE | B_DELWRI)) {
1348Sbill 			brelse(rabp);
13540341Smckusick 			trace(TR_BREADHITRA, pack(vp, rabsize), rablkno);
1362045Swnj 		} else {
13746151Smckusick 			rabp->b_flags |= B_ASYNC | B_READ;
1388670S 			if (rabp->b_bcount > rabp->b_bufsize)
1398670S 				panic("breadrabp");
14038880Smckusick 			if (rabp->b_rcred == NOCRED && cred != NOCRED) {
14138776Smckusick 				crhold(cred);
14238880Smckusick 				rabp->b_rcred = cred;
14338776Smckusick 			}
14437736Smckusick 			VOP_STRATEGY(rabp);
14540341Smckusick 			trace(TR_BREADMISSRA, pack(vp, rabsize), rablkno);
14647545Skarels 			p->p_stats->p_ru.ru_inblock++;	/* pay in advance */
1478Sbill 		}
1488Sbill 	}
1497015Smckusick 
1507015Smckusick 	/*
15146151Smckusick 	 * If block was memory resident, let bread get it.
15246151Smckusick 	 * If block was not memory resident, the read was
15346151Smckusick 	 * started above, so just wait for the read to complete.
1547015Smckusick 	 */
1557114Smckusick 	if (bp == NULL)
15638776Smckusick 		return (bread(vp, blkno, size, cred, bpp));
15737736Smckusick 	return (biowait(bp));
1588Sbill }
1598Sbill 
1608Sbill /*
16146151Smckusick  * Synchronous write.
16246151Smckusick  * Release buffer on completion.
1638Sbill  */
1648Sbill bwrite(bp)
1657015Smckusick 	register struct buf *bp;
1668Sbill {
16747545Skarels 	struct proc *p = curproc;		/* XXX */
16837736Smckusick 	register int flag;
16940226Smckusick 	int s, error;
1708Sbill 
1718Sbill 	flag = bp->b_flags;
1729857Ssam 	bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI);
17346151Smckusick 	if ((flag & B_DELWRI) == 0)
17447545Skarels 		p->p_stats->p_ru.ru_oublock++;		/* no one paid yet */
17539882Smckusick 	else
17639882Smckusick 		reassignbuf(bp, bp->b_vp);
17740341Smckusick 	trace(TR_BWRITE, pack(bp->b_vp, bp->b_bcount), bp->b_lblkno);
1788670S 	if (bp->b_bcount > bp->b_bufsize)
1798670S 		panic("bwrite");
18040226Smckusick 	s = splbio();
18139882Smckusick 	bp->b_vp->v_numoutput++;
18240226Smckusick 	splx(s);
18337736Smckusick 	VOP_STRATEGY(bp);
1847015Smckusick 
1857015Smckusick 	/*
18646151Smckusick 	 * If the write was synchronous, then await I/O completion.
1877015Smckusick 	 * If the write was "delayed", then we put the buffer on
18846151Smckusick 	 * the queue of blocks awaiting I/O completion status.
1897015Smckusick 	 */
19046151Smckusick 	if ((flag & B_ASYNC) == 0) {
19137736Smckusick 		error = biowait(bp);
1928Sbill 		brelse(bp);
19337736Smckusick 	} else if (flag & B_DELWRI) {
1948Sbill 		bp->b_flags |= B_AGE;
19537736Smckusick 		error = 0;
19637736Smckusick 	}
19737736Smckusick 	return (error);
1988Sbill }
1998Sbill 
2008Sbill /*
20146151Smckusick  * Delayed write.
20246151Smckusick  *
20346151Smckusick  * The buffer is marked dirty, but is not queued for I/O.
20446151Smckusick  * This routine should be used when the buffer is expected
20546151Smckusick  * to be modified again soon, typically a small write that
20646151Smckusick  * partially fills a buffer.
20746151Smckusick  *
20846151Smckusick  * NB: magnetic tapes cannot be delayed; they must be
20946151Smckusick  * written in the order that the writes are requested.
2108Sbill  */
2118Sbill bdwrite(bp)
2127015Smckusick 	register struct buf *bp;
2138Sbill {
21447545Skarels 	struct proc *p = curproc;		/* XXX */
2158Sbill 
21639882Smckusick 	if ((bp->b_flags & B_DELWRI) == 0) {
21739882Smckusick 		bp->b_flags |= B_DELWRI;
21839882Smckusick 		reassignbuf(bp, bp->b_vp);
21947545Skarels 		p->p_stats->p_ru.ru_oublock++;		/* no one paid yet */
22039882Smckusick 	}
22137736Smckusick 	/*
22239668Smckusick 	 * If this is a tape drive, the write must be initiated.
22337736Smckusick 	 */
22448360Smckusick 	if (VOP_IOCTL(bp->b_vp, 0, (caddr_t)B_TAPE, 0, NOCRED, p) == 0) {
2258Sbill 		bawrite(bp);
22639668Smckusick 	} else {
22746151Smckusick 		bp->b_flags |= (B_DONE | B_DELWRI);
2288Sbill 		brelse(bp);
2298Sbill 	}
2308Sbill }
2318Sbill 
2328Sbill /*
23346151Smckusick  * Asynchronous write.
23446151Smckusick  * Start I/O on a buffer, but do not wait for it to complete.
23546151Smckusick  * The buffer is released when the I/O completes.
2368Sbill  */
2378Sbill bawrite(bp)
2387015Smckusick 	register struct buf *bp;
2398Sbill {
2408Sbill 
24146151Smckusick 	/*
24246151Smckusick 	 * Setting the ASYNC flag causes bwrite to return
24346151Smckusick 	 * after starting the I/O.
24446151Smckusick 	 */
2458Sbill 	bp->b_flags |= B_ASYNC;
24637736Smckusick 	(void) bwrite(bp);
2478Sbill }
2488Sbill 
2498Sbill /*
25046151Smckusick  * Release a buffer.
25146151Smckusick  * Even if the buffer is dirty, no I/O is started.
2528Sbill  */
2538Sbill brelse(bp)
2547015Smckusick 	register struct buf *bp;
2558Sbill {
2562325Swnj 	register struct buf *flist;
25746151Smckusick 	int s;
2588Sbill 
25940341Smckusick 	trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno);
2607015Smckusick 	/*
26139668Smckusick 	 * If a process is waiting for the buffer, or
26239668Smckusick 	 * is waiting for a free buffer, awaken it.
2637015Smckusick 	 */
26446151Smckusick 	if (bp->b_flags & B_WANTED)
2658Sbill 		wakeup((caddr_t)bp);
26646151Smckusick 	if (bfreelist[0].b_flags & B_WANTED) {
2672325Swnj 		bfreelist[0].b_flags &= ~B_WANTED;
2682325Swnj 		wakeup((caddr_t)bfreelist);
2698Sbill 	}
27039668Smckusick 	/*
27139668Smckusick 	 * Retry I/O for locked buffers rather than invalidating them.
27239668Smckusick 	 */
27339668Smckusick 	if ((bp->b_flags & B_ERROR) && (bp->b_flags & B_LOCKED))
27439668Smckusick 		bp->b_flags &= ~B_ERROR;
27539668Smckusick 	/*
27639668Smckusick 	 * Disassociate buffers that are no longer valid.
27739668Smckusick 	 */
27846151Smckusick 	if (bp->b_flags & (B_NOCACHE | B_ERROR))
27937736Smckusick 		bp->b_flags |= B_INVAL;
28046151Smckusick 	if ((bp->b_bufsize <= 0) || (bp->b_flags & (B_ERROR | B_INVAL))) {
28139668Smckusick 		if (bp->b_vp)
28239668Smckusick 			brelvp(bp);
28339668Smckusick 		bp->b_flags &= ~B_DELWRI;
28437736Smckusick 	}
2857015Smckusick 	/*
2867015Smckusick 	 * Stick the buffer back on a free list.
2877015Smckusick 	 */
28826271Skarels 	s = splbio();
2898670S 	if (bp->b_bufsize <= 0) {
2908670S 		/* block has no buffer ... put at front of unused buffer list */
2918670S 		flist = &bfreelist[BQ_EMPTY];
2928670S 		binsheadfree(bp, flist);
29346151Smckusick 	} else if (bp->b_flags & (B_ERROR | B_INVAL)) {
2942325Swnj 		/* block has no info ... put at front of most free list */
2958670S 		flist = &bfreelist[BQ_AGE];
2967015Smckusick 		binsheadfree(bp, flist);
2978Sbill 	} else {
2982325Swnj 		if (bp->b_flags & B_LOCKED)
2992325Swnj 			flist = &bfreelist[BQ_LOCKED];
3002325Swnj 		else if (bp->b_flags & B_AGE)
3012325Swnj 			flist = &bfreelist[BQ_AGE];
3022325Swnj 		else
3032325Swnj 			flist = &bfreelist[BQ_LRU];
3047015Smckusick 		binstailfree(bp, flist);
3058Sbill 	}
30646151Smckusick 	bp->b_flags &= ~(B_WANTED | B_BUSY | B_ASYNC | B_AGE | B_NOCACHE);
3078Sbill 	splx(s);
3088Sbill }
3098Sbill 
3108Sbill /*
31146151Smckusick  * Check to see if a block is currently memory resident.
3128Sbill  */
31337736Smckusick incore(vp, blkno)
31437736Smckusick 	struct vnode *vp;
3157015Smckusick 	daddr_t blkno;
3168Sbill {
3178Sbill 	register struct buf *bp;
3182325Swnj 	register struct buf *dp;
3198Sbill 
32038225Smckusick 	dp = BUFHASH(vp, blkno);
3212325Swnj 	for (bp = dp->b_forw; bp != dp; bp = bp->b_forw)
32239668Smckusick 		if (bp->b_lblkno == blkno && bp->b_vp == vp &&
3237015Smckusick 		    (bp->b_flags & B_INVAL) == 0)
32491Sbill 			return (1);
32591Sbill 	return (0);
3268Sbill }
3278Sbill 
32839668Smckusick /*
32946151Smckusick  * Check to see if a block is currently memory resident.
33046151Smckusick  * If it is resident, return it. If it is not resident,
33146151Smckusick  * allocate a new buffer and assign it to the block.
33239668Smckusick  */
3338Sbill struct buf *
33437736Smckusick getblk(vp, blkno, size)
33537736Smckusick 	register struct vnode *vp;
3366563Smckusic 	daddr_t blkno;
3376563Smckusic 	int size;
3388Sbill {
3398670S 	register struct buf *bp, *dp;
3405424Swnj 	int s;
3418Sbill 
34225255Smckusick 	if (size > MAXBSIZE)
34325255Smckusick 		panic("getblk: size too big");
3447015Smckusick 	/*
34546151Smckusick 	 * Search the cache for the block. If the buffer is found,
34646151Smckusick 	 * but it is currently locked, the we must wait for it to
34746151Smckusick 	 * become available.
3487015Smckusick 	 */
34937736Smckusick 	dp = BUFHASH(vp, blkno);
3507015Smckusick loop:
3512325Swnj 	for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) {
35239668Smckusick 		if (bp->b_lblkno != blkno || bp->b_vp != vp ||
35346151Smckusick 		    (bp->b_flags & B_INVAL))
3548Sbill 			continue;
35526271Skarels 		s = splbio();
35646151Smckusick 		if (bp->b_flags & B_BUSY) {
3578Sbill 			bp->b_flags |= B_WANTED;
35846151Smckusick 			sleep((caddr_t)bp, PRIBIO + 1);
3595424Swnj 			splx(s);
3608Sbill 			goto loop;
3618Sbill 		}
36239882Smckusick 		bremfree(bp);
36339882Smckusick 		bp->b_flags |= B_BUSY;
3645424Swnj 		splx(s);
36532608Smckusick 		if (bp->b_bcount != size) {
36639668Smckusick 			printf("getblk: stray size");
36739668Smckusick 			bp->b_flags |= B_INVAL;
36839668Smckusick 			bwrite(bp);
36939668Smckusick 			goto loop;
37032608Smckusick 		}
3718Sbill 		bp->b_flags |= B_CACHE;
37226271Skarels 		return (bp);
3738Sbill 	}
3748670S 	bp = getnewbuf();
3757015Smckusick 	bremhash(bp);
37639668Smckusick 	bgetvp(vp, bp);
37745116Smckusick 	bp->b_bcount = 0;
37839668Smckusick 	bp->b_lblkno = blkno;
3796563Smckusic 	bp->b_blkno = blkno;
3808670S 	bp->b_error = 0;
38137736Smckusick 	bp->b_resid = 0;
38237736Smckusick 	binshash(bp, dp);
38345116Smckusick 	allocbuf(bp, size);
38426271Skarels 	return (bp);
3858Sbill }
3868Sbill 
3878Sbill /*
38846151Smckusick  * Allocate a buffer.
38946151Smckusick  * The caller will assign it to a block.
3908Sbill  */
3918Sbill struct buf *
3926563Smckusic geteblk(size)
3936563Smckusic 	int size;
3948Sbill {
3958670S 	register struct buf *bp, *flist;
3968Sbill 
39725255Smckusick 	if (size > MAXBSIZE)
39825255Smckusick 		panic("geteblk: size too big");
3998670S 	bp = getnewbuf();
4008670S 	bp->b_flags |= B_INVAL;
4017015Smckusick 	bremhash(bp);
4028670S 	flist = &bfreelist[BQ_AGE];
40345116Smckusick 	bp->b_bcount = 0;
40437736Smckusick 	bp->b_error = 0;
40537736Smckusick 	bp->b_resid = 0;
4068670S 	binshash(bp, flist);
40745116Smckusick 	allocbuf(bp, size);
40826271Skarels 	return (bp);
4098Sbill }
4108Sbill 
4118Sbill /*
41245116Smckusick  * Expand or contract the actual memory allocated to a buffer.
41346151Smckusick  * If no memory is available, release buffer and take error exit.
4146563Smckusic  */
41545116Smckusick allocbuf(tp, size)
41645116Smckusick 	register struct buf *tp;
4176563Smckusic 	int size;
4186563Smckusic {
41945116Smckusick 	register struct buf *bp, *ep;
42045116Smckusick 	int sizealloc, take, s;
4216563Smckusic 
42245116Smckusick 	sizealloc = roundup(size, CLBYTES);
42345116Smckusick 	/*
42445116Smckusick 	 * Buffer size does not change
42545116Smckusick 	 */
42645116Smckusick 	if (sizealloc == tp->b_bufsize)
42745116Smckusick 		goto out;
42845116Smckusick 	/*
42945116Smckusick 	 * Buffer size is shrinking.
43045116Smckusick 	 * Place excess space in a buffer header taken from the
43145116Smckusick 	 * BQ_EMPTY buffer list and placed on the "most free" list.
43245116Smckusick 	 * If no extra buffer headers are available, leave the
43345116Smckusick 	 * extra space in the present buffer.
43445116Smckusick 	 */
43545116Smckusick 	if (sizealloc < tp->b_bufsize) {
43645116Smckusick 		ep = bfreelist[BQ_EMPTY].av_forw;
43745116Smckusick 		if (ep == &bfreelist[BQ_EMPTY])
43845116Smckusick 			goto out;
43945116Smckusick 		s = splbio();
44045116Smckusick 		bremfree(ep);
44145116Smckusick 		ep->b_flags |= B_BUSY;
44245116Smckusick 		splx(s);
44345116Smckusick 		pagemove(tp->b_un.b_addr + sizealloc, ep->b_un.b_addr,
44445116Smckusick 		    (int)tp->b_bufsize - sizealloc);
44545116Smckusick 		ep->b_bufsize = tp->b_bufsize - sizealloc;
44645116Smckusick 		tp->b_bufsize = sizealloc;
44745116Smckusick 		ep->b_flags |= B_INVAL;
44845116Smckusick 		ep->b_bcount = 0;
44945116Smckusick 		brelse(ep);
45045116Smckusick 		goto out;
45145116Smckusick 	}
45245116Smckusick 	/*
45345116Smckusick 	 * More buffer space is needed. Get it out of buffers on
45445116Smckusick 	 * the "most free" list, placing the empty headers on the
45545116Smckusick 	 * BQ_EMPTY buffer header list.
45645116Smckusick 	 */
45745116Smckusick 	while (tp->b_bufsize < sizealloc) {
45845116Smckusick 		take = sizealloc - tp->b_bufsize;
45945116Smckusick 		bp = getnewbuf();
46045116Smckusick 		if (take >= bp->b_bufsize)
46145116Smckusick 			take = bp->b_bufsize;
46245116Smckusick 		pagemove(&bp->b_un.b_addr[bp->b_bufsize - take],
46345116Smckusick 		    &tp->b_un.b_addr[tp->b_bufsize], take);
46445116Smckusick 		tp->b_bufsize += take;
46545116Smckusick 		bp->b_bufsize = bp->b_bufsize - take;
46645116Smckusick 		if (bp->b_bcount > bp->b_bufsize)
46745116Smckusick 			bp->b_bcount = bp->b_bufsize;
46845116Smckusick 		if (bp->b_bufsize <= 0) {
46945116Smckusick 			bremhash(bp);
47045116Smckusick 			binshash(bp, &bfreelist[BQ_EMPTY]);
47146151Smckusick 			bp->b_dev = NODEV;
47245116Smckusick 			bp->b_error = 0;
47345116Smckusick 			bp->b_flags |= B_INVAL;
47445116Smckusick 		}
47545116Smckusick 		brelse(bp);
47645116Smckusick 	}
47745116Smckusick out:
47845116Smckusick 	tp->b_bcount = size;
47945116Smckusick 	return (1);
4808670S }
4818670S 
4828670S /*
4838670S  * Find a buffer which is available for use.
4848670S  * Select something from a free list.
4858670S  * Preference is to AGE list, then LRU list.
4868670S  */
4878670S struct buf *
4888670S getnewbuf()
4898670S {
4908670S 	register struct buf *bp, *dp;
49138776Smckusick 	register struct ucred *cred;
4928670S 	int s;
4938670S 
4948670S loop:
49526271Skarels 	s = splbio();
4968670S 	for (dp = &bfreelist[BQ_AGE]; dp > bfreelist; dp--)
4978670S 		if (dp->av_forw != dp)
4988670S 			break;
4998670S 	if (dp == bfreelist) {		/* no free blocks */
5008670S 		dp->b_flags |= B_WANTED;
50146151Smckusick 		sleep((caddr_t)dp, PRIBIO + 1);
50212170Ssam 		splx(s);
5038670S 		goto loop;
5048670S 	}
50539882Smckusick 	bp = dp->av_forw;
50639882Smckusick 	bremfree(bp);
50739882Smckusick 	bp->b_flags |= B_BUSY;
5088670S 	splx(s);
5098670S 	if (bp->b_flags & B_DELWRI) {
51038614Smckusick 		(void) bawrite(bp);
5118670S 		goto loop;
5128670S 	}
51340341Smckusick 	trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno);
51439668Smckusick 	if (bp->b_vp)
51539668Smckusick 		brelvp(bp);
51638776Smckusick 	if (bp->b_rcred != NOCRED) {
51738776Smckusick 		cred = bp->b_rcred;
51838776Smckusick 		bp->b_rcred = NOCRED;
51938776Smckusick 		crfree(cred);
52038776Smckusick 	}
52138776Smckusick 	if (bp->b_wcred != NOCRED) {
52238776Smckusick 		cred = bp->b_wcred;
52338776Smckusick 		bp->b_wcred = NOCRED;
52438776Smckusick 		crfree(cred);
52538776Smckusick 	}
5268670S 	bp->b_flags = B_BUSY;
52746989Smckusick 	bp->b_dirtyoff = bp->b_dirtyend = 0;
5288670S 	return (bp);
5298670S }
5308670S 
5318670S /*
53246151Smckusick  * Wait for I/O to complete.
53346151Smckusick  *
53446151Smckusick  * Extract and return any errors associated with the I/O.
53546151Smckusick  * If the error flag is set, but no specific error is
53646151Smckusick  * given, return EIO.
5378Sbill  */
5387015Smckusick biowait(bp)
5396563Smckusic 	register struct buf *bp;
5408Sbill {
5415431Sroot 	int s;
5428Sbill 
54326271Skarels 	s = splbio();
54438776Smckusick 	while ((bp->b_flags & B_DONE) == 0)
5458Sbill 		sleep((caddr_t)bp, PRIBIO);
5465431Sroot 	splx(s);
54737736Smckusick 	if ((bp->b_flags & B_ERROR) == 0)
54837736Smckusick 		return (0);
54937736Smckusick 	if (bp->b_error)
55037736Smckusick 		return (bp->b_error);
55137736Smckusick 	return (EIO);
5528Sbill }
5538Sbill 
5548Sbill /*
55513128Ssam  * Mark I/O complete on a buffer.
55646151Smckusick  *
55746151Smckusick  * If a callback has been requested, e.g. the pageout
55846151Smckusick  * daemon, do so. Otherwise, awaken waiting processes.
5598Sbill  */
5607015Smckusick biodone(bp)
5617015Smckusick 	register struct buf *bp;
5628Sbill {
5638Sbill 
564420Sbill 	if (bp->b_flags & B_DONE)
5657015Smckusick 		panic("dup biodone");
5668Sbill 	bp->b_flags |= B_DONE;
56749232Smckusick 	if ((bp->b_flags & B_READ) == 0)
56849232Smckusick 		vwakeup(bp);
5699763Ssam 	if (bp->b_flags & B_CALL) {
5709763Ssam 		bp->b_flags &= ~B_CALL;
5719763Ssam 		(*bp->b_iodone)(bp);
5729763Ssam 		return;
5739763Ssam 	}
57446151Smckusick 	if (bp->b_flags & B_ASYNC)
5758Sbill 		brelse(bp);
5768Sbill 	else {
5778Sbill 		bp->b_flags &= ~B_WANTED;
5788Sbill 		wakeup((caddr_t)bp);
5798Sbill 	}
5808Sbill }
581