svn commit: r189933 - head/sys/kern

Attilio Rao attilio at FreeBSD.org
Tue Mar 17 09:30:50 PDT 2009


Author: attilio
Date: Tue Mar 17 16:30:49 2009
New Revision: 189933
URL: http://svn.freebsd.org/changeset/base/189933

Log:
  Fix an old-standing bug that crept in along the several revisions:
  B_DELWRI cleanup and vnode disassociation should happen just before to
  assign the buffer to a queue.
  
  Reported by:	miwi, Volker <volker at vwsoft dot com>,
  		Ben Kaduk <minimarmot at gmail dot com>,
  		Christopher Mallon <christoph dot mallon at gmx dot de>
  Tested by:	lulf, miwi

Modified:
  head/sys/kern/vfs_bio.c

Modified: head/sys/kern/vfs_bio.c
==============================================================================
--- head/sys/kern/vfs_bio.c	Tue Mar 17 14:53:42 2009	(r189932)
+++ head/sys/kern/vfs_bio.c	Tue Mar 17 16:30:49 2009	(r189933)
@@ -1369,9 +1369,23 @@ brelse(struct buf *bp)
 	if (bp->b_qindex != QUEUE_NONE)
 		panic("brelse: free buffer onto another queue???");
 
+	/*
+	 * If the buffer has junk contents signal it and eventually
+	 * clean up B_DELWRI and diassociate the vnode so that gbincore()
+	 * doesn't find it.
+	 */
+	if (bp->b_bufsize == 0 || (bp->b_ioflags & BIO_ERROR) != 0 ||
+	    (bp->b_flags & (B_INVAL | B_NOCACHE | B_RELBUF)) != 0)
+		bp->b_flags |= B_INVAL;
+	if (bp->b_flags & B_INVAL) {
+		if (bp->b_flags & B_DELWRI)
+			bundirty(bp);
+		if (bp->b_vp)
+			brelvp(bp);
+	}
+
 	/* buffers with no memory */
 	if (bp->b_bufsize == 0) {
-		bp->b_flags |= B_INVAL;
 		bp->b_xflags &= ~(BX_BKGRDWRITE | BX_ALTDATA);
 		if (bp->b_vflags & BV_BKGRDINPROG)
 			panic("losing buffer 1");
@@ -1384,7 +1398,6 @@ brelse(struct buf *bp)
 	/* buffers with junk contents */
 	} else if (bp->b_flags & (B_INVAL | B_NOCACHE | B_RELBUF) ||
 	    (bp->b_ioflags & BIO_ERROR)) {
-		bp->b_flags |= B_INVAL;
 		bp->b_xflags &= ~(BX_BKGRDWRITE | BX_ALTDATA);
 		if (bp->b_vflags & BV_BKGRDINPROG)
 			panic("losing buffer 2");
@@ -1407,19 +1420,6 @@ brelse(struct buf *bp)
 	mtx_unlock(&bqlock);
 
 	/*
-	 * If B_INVAL and B_DELWRI is set, clear B_DELWRI.  We have already
-	 * placed the buffer on the correct queue.  We must also disassociate
-	 * the device and vnode for a B_INVAL buffer so gbincore() doesn't
-	 * find it.
-	 */
-	if (bp->b_flags & B_INVAL) {
-		if (bp->b_flags & B_DELWRI)
-			bundirty(bp);
-		if (bp->b_vp)
-			brelvp(bp);
-	}
-
-	/*
 	 * Fixup numfreebuffers count.  The bp is on an appropriate queue
 	 * unless locked.  We then bump numfreebuffers if it is not B_DELWRI.
 	 * We've already handled the B_INVAL case ( B_DELWRI will be clear


More information about the svn-src-all mailing list