Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 27 Feb 2013 07:34:09 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r247389 - head/sys/kern
Message-ID:  <201302270734.r1R7Y9Tu057323@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Feb 27 07:34:09 2013
New Revision: 247389
URL: http://svnweb.freebsd.org/changeset/base/247389

Log:
  Make recursive getblk() slightly more useful.  Keep the buffer state
  intact if getblk() is done on the already owned buffer.  Exit from
  brelse() early when the lock recursion is detected, otherwise brelse()
  might prematurely destroy the buffer under some circumstances.
  
  Sponsored by:	The FreeBSD Foundation
  Noted by:	mckusick
  Tested by:	pho
  MFC after:	2 weeks

Modified:
  head/sys/kern/vfs_bio.c

Modified: head/sys/kern/vfs_bio.c
==============================================================================
--- head/sys/kern/vfs_bio.c	Wed Feb 27 07:32:39 2013	(r247388)
+++ head/sys/kern/vfs_bio.c	Wed Feb 27 07:34:09 2013	(r247389)
@@ -1268,6 +1268,15 @@ brelse(struct buf *bp)
 	KASSERT(!(bp->b_flags & (B_CLUSTER|B_PAGING)),
 	    ("brelse: inappropriate B_PAGING or B_CLUSTER bp %p", bp));
 
+	if (BUF_LOCKRECURSED(bp)) {
+		/*
+		 * Do not process, in particular, do not handle the
+		 * B_INVAL/B_RELBUF and do not release to free list.
+		 */
+		BUF_UNLOCK(bp);
+		return;
+	}
+
 	if (bp->b_flags & B_MANAGED) {
 		bqrelse(bp);
 		return;
@@ -1444,12 +1453,6 @@ brelse(struct buf *bp)
 			brelvp(bp);
 	}
 			
-	if (BUF_LOCKRECURSED(bp)) {
-		/* do not release to free list */
-		BUF_UNLOCK(bp);
-		return;
-	}
-
 	/* enqueue */
 	mtx_lock(&bqlock);
 	/* Handle delayed bremfree() processing. */
@@ -2681,6 +2684,9 @@ loop:
 		/* We timed out or were interrupted. */
 		else if (error)
 			return (NULL);
+		/* If recursed, assume caller knows the rules. */
+		else if (BUF_LOCKRECURSED(bp))
+			goto end;
 
 		/*
 		 * The buffer is locked.  B_CACHE is cleared if the buffer is 
@@ -2864,6 +2870,7 @@ loop:
 	}
 	CTR4(KTR_BUF, "getblk(%p, %ld, %d) = %p", vp, (long)blkno, size, bp);
 	BUF_ASSERT_HELD(bp);
+end:
 	KASSERT(bp->b_bufobj == bo,
 	    ("bp %p wrong b_bufobj %p should be %p", bp, bp->b_bufobj, bo));
 	return (bp);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201302270734.r1R7Y9Tu057323>