If an asynchronous request invalidates a buf, then we might remove it
authormatthew <matthew@openbsd.org>
Tue, 3 Aug 2010 04:10:16 +0000 (04:10 +0000)
committermatthew <matthew@openbsd.org>
Tue, 3 Aug 2010 04:10:16 +0000 (04:10 +0000)
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@

sys/kern/vfs_bio.c

index 774dfc7..0b7b2cc 100644 (file)
@@ -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;