summaryrefslogtreecommitdiff
path: root/sys/kern/vfs_bio.c
diff options
context:
space:
mode:
authorMatthew Dempsky <matthew@cvs.openbsd.org>2010-08-03 04:10:17 +0000
committerMatthew Dempsky <matthew@cvs.openbsd.org>2010-08-03 04:10:17 +0000
commit2ba8447047a1f10958bab7730c1673cf29ffd525 (patch)
treede4b9057eb4a19fdff93bdadca09660b1ea95867 /sys/kern/vfs_bio.c
parent1cff5c2207ba8e29a5394401c702b28e0eaba9cf (diff)
If an asynchronous request invalidates a buf, then we might remove it
from its vnode's buffer cache in an interrupt context. Therefore we need interrupt protection when searching the buffer red-black tree. ok deraadt@, thib@, art@
Diffstat (limited to 'sys/kern/vfs_bio.c')
-rw-r--r--sys/kern/vfs_bio.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 774dfc794ff..0b7b2ccde22 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_bio.c,v 1.124 2010/07/01 16:23:09 thib Exp $ */
+/* $OpenBSD: vfs_bio.c,v 1.125 2010/08/03 04:10:16 matthew Exp $ */
/* $NetBSD: vfs_bio.c,v 1.44 1996/06/11 11:15:36 pk Exp $ */
/*
@@ -873,12 +873,17 @@ incore(struct vnode *vp, daddr64_t blkno)
{
struct buf *bp;
struct buf b;
+ int s;
+
+ s = splbio();
/* Search buf lookup tree */
b.b_lblkno = blkno;
bp = RB_FIND(buf_rb_bufs, &vp->v_bufs_tree, &b);
- if (bp && !ISSET(bp->b_flags, B_INVAL))
- return(bp);
+ if (bp != NULL && ISSET(bp->b_flags, B_INVAL))
+ bp = NULL;
+
+ splx(s);
return(NULL);
}
@@ -908,11 +913,10 @@ getblk(struct vnode *vp, daddr64_t blkno, int size, int slpflag, int slptimeo)
* the block until the write is finished.
*/
start:
+ s = splbio();
b.b_lblkno = blkno;
bp = RB_FIND(buf_rb_bufs, &vp->v_bufs_tree, &b);
if (bp != NULL) {
-
- s = splbio();
if (ISSET(bp->b_flags, B_BUSY)) {
SET(bp->b_flags, B_WANTED);
error = tsleep(bp, slpflag | (PRIBIO + 1), "getblk",
@@ -931,8 +935,8 @@ start:
splx(s);
return (bp);
}
- splx(s);
}
+ splx(s);
if ((bp = buf_get(vp, blkno, size)) == NULL)
goto start;