summaryrefslogtreecommitdiff
path: root/sys/kern/vfs_bio.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/vfs_bio.c')
-rw-r--r--sys/kern/vfs_bio.c57
1 files changed, 39 insertions, 18 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 630456a512b..e088c881714 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_bio.c,v 1.38 2001/05/05 20:57:01 art Exp $ */
+/* $OpenBSD: vfs_bio.c,v 1.39 2001/08/30 12:38:52 gluk Exp $ */
/* $NetBSD: vfs_bio.c,v 1.44 1996/06/11 11:15:36 pk Exp $ */
/*-
@@ -107,6 +107,7 @@ struct bio_ops bioops;
static __inline struct buf *bio_doread __P((struct vnode *, daddr_t, int,
struct ucred *, int));
int count_lock_queue __P((void));
+int getnewbuf __P((int slpflag, int slptimeo, struct buf **));
/*
* We keep a few counters to monitor the utilization of the buffer cache
@@ -678,7 +679,7 @@ getblk(vp, blkno, size, slpflag, slptimeo)
int size, slpflag, slptimeo;
{
struct bufhashhdr *bh;
- struct buf *bp;
+ struct buf *bp, *nbp = NULL;
int s, err;
/*
@@ -719,13 +720,17 @@ start:
}
if (bp == NULL) {
- if ((bp = getnewbuf(slpflag, slptimeo)) == NULL)
+ if (nbp == NULL && getnewbuf(slpflag, slptimeo, &nbp) != 0) {
goto start;
+ }
+ bp = nbp;
binshash(bp, bh);
bp->b_blkno = bp->b_lblkno = blkno;
s = splbio();
bgetvp(vp, bp);
splx(s);
+ } else if (nbp != NULL) {
+ brelse(nbp);
}
allocbuf(bp, size);
@@ -741,8 +746,7 @@ geteblk(size)
{
struct buf *bp;
- while ((bp = getnewbuf(0, 0)) == 0)
- ;
+ getnewbuf(0, 0, &bp);
SET(bp->b_flags, B_INVAL);
binshash(bp, &invalhash);
allocbuf(bp, size);
@@ -783,8 +787,7 @@ allocbuf(bp, size)
int amt;
/* find a buffer */
- while ((nbp = getnewbuf(0, 0)) == NULL)
- ;
+ getnewbuf(0, 0, &nbp);
SET(nbp->b_flags, B_INVAL);
binshash(nbp, &invalhash);
@@ -844,13 +847,21 @@ out:
* Find a buffer which is available for use.
* Select something from a free list.
* Preference is to AGE list, then LRU list.
+ *
+ * We must notify getblk if we slept during the buffer allocation. When
+ * that happens, we allocate a buffer anyway (unless tsleep is interrupted
+ * or times out) and return !0.
*/
-struct buf *
-getnewbuf(slpflag, slptimeo)
+int
+getnewbuf(slpflag, slptimeo, bpp)
int slpflag, slptimeo;
+ struct buf **bpp;
{
- register struct buf *bp;
- int s;
+ struct buf *bp;
+ int s, ret, error;
+
+ *bpp = NULL;
+ ret = 0;
start:
s = splbio();
@@ -863,18 +874,25 @@ start:
if ((numcleanbufs <= locleanbufs) && curproc != syncerproc) {
/* wait for a free buffer of any kind */
needbuffer++;
- tsleep(&needbuffer, slpflag|(PRIBIO+1), "getnewbuf", slptimeo);
+ error = tsleep(&needbuffer, slpflag|(PRIBIO+1), "getnewbuf",
+ slptimeo);
splx(s);
- return (0);
+ if (error)
+ return (1);
+ ret = 1;
+ goto start;
}
if ((bp = bufqueues[BQ_AGE].tqh_first) == NULL &&
(bp = bufqueues[BQ_LRU].tqh_first) == NULL) {
/* wait for a free buffer of any kind */
syncer_needbuffer = 1;
- tsleep(&syncer_needbuffer, slpflag|(PRIBIO-3), "getnewbuf",
- slptimeo);
+ error = tsleep(&syncer_needbuffer, slpflag|(PRIBIO-3),
+ "getnewbuf", slptimeo);
splx(s);
- return (0);
+ if (error)
+ return (1);
+ ret = 1;
+ goto start;
}
bremfree(bp);
@@ -903,7 +921,9 @@ start:
*/
SET(bp->b_flags, B_AGE);
bawrite(bp);
- return (0);
+ /* bawrite can sleep, return 1 */
+ ret = 1;
+ goto start;
}
/* disassociate us from our vnode, if we had one... */
@@ -937,7 +957,8 @@ start:
}
bremhash(bp);
- return (bp);
+ *bpp = bp;
+ return (ret);
}
/*