Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 7 Feb 2018 01:24:49 +0000 (UTC)
From:      Jeff Roberson <jeff@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r328963 - user/jeff/numa/sys/kern
Message-ID:  <201802070124.w171OnSb035334@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jeff
Date: Wed Feb  7 01:24:49 2018
New Revision: 328963
URL: https://svnweb.freebsd.org/changeset/base/328963

Log:
  The buf queue may change while the buf is locked.  This can only occur when
  it is being pushed from a per-cpu queue to the cleanq.  Detect this
  condition in bufqueue_acquire().
  
  Reported by:	pho

Modified:
  user/jeff/numa/sys/kern/vfs_bio.c

Modified: user/jeff/numa/sys/kern/vfs_bio.c
==============================================================================
--- user/jeff/numa/sys/kern/vfs_bio.c	Wed Feb  7 00:50:40 2018	(r328962)
+++ user/jeff/numa/sys/kern/vfs_bio.c	Wed Feb  7 01:24:49 2018	(r328963)
@@ -1309,6 +1309,7 @@ static struct bufqueue *
 bufqueue(struct buf *bp)
 {
 	struct bufdomain *bd;
+	int cpu;
 
 	switch (bp->b_qindex) {
 	case QUEUE_NONE:
@@ -1326,10 +1327,37 @@ bufqueue(struct buf *bp)
 		panic("bufqueue(%p): Unhandled type %d\n", bp, bp->b_qindex);
 	}
 	bd = &bdclean[bp->b_domain];
-	if (bp->b_cpu > mp_maxid)
+	/* cpu may be changed by bd_flush().  Read it only once. */
+	cpu = bp->b_cpu;
+	if (cpu > mp_maxid)
 		return (&bd->bd_cleanq);
-	return (&bd->bd_cpuq[bp->b_cpu]);
+	return (&bd->bd_cpuq[cpu]);
+}
 
+/*
+ * Return the locked bufqueue that bp is a member of.
+ */
+static struct bufqueue *
+bufqueue_acquire(struct buf *bp)
+{
+	struct bufqueue *bq, *nbq;
+
+	/*
+	 * bp can be pushed from a per-cpu queue to the
+	 * cleanq while we're waiting on the lock.  Retry
+	 * if the queues don't match.
+	 */
+	bq = bufqueue(bp);
+	BQ_LOCK(bq);
+	for (;;) {
+		nbq = bufqueue(bp);
+		if (bq == nbq)
+			break;
+		BQ_UNLOCK(bq);
+		BQ_LOCK(nbq);
+		bq = nbq;
+	}
+	return (bq);
 }
 
 /*
@@ -1358,8 +1386,7 @@ binsfree(struct buf *bp, int qindex)
 			BUF_UNLOCK(bp);
 			return;
 		}
-		bq = bufqueue(bp);
-		BQ_LOCK(bq);
+		bq = bufqueue_acquire(bp);
 		bq_remove(bq, bp);
 		BQ_UNLOCK(bq);
 	}
@@ -1647,8 +1674,7 @@ bremfreef(struct buf *bp)
 {
 	struct bufqueue *bq;
 
-	bq = bufqueue(bp);
-	BQ_LOCK(bq);
+	bq = bufqueue_acquire(bp);
 	bq_remove(bq, bp);
 	BQ_UNLOCK(bq);
 }



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