Module Name:    src
Committed By:   mlelstv
Date:           Thu Dec 22 13:42:15 UTC 2016

Modified Files:
        src/sys/dev: dksubr.c dkvar.h
        src/sys/sys: param.h

Log Message:
Fix race condition in dksubr, where a dk_start from another thread
or interrupt was ignored while the queue was processed.

Bump kernel revision for changed dk_softc.


To generate a diff of this commit:
cvs rdiff -u -r1.93 -r1.94 src/sys/dev/dksubr.c
cvs rdiff -u -r1.27 -r1.28 src/sys/dev/dkvar.h
cvs rdiff -u -r1.518 -r1.519 src/sys/sys/param.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/dksubr.c
diff -u src/sys/dev/dksubr.c:1.93 src/sys/dev/dksubr.c:1.94
--- src/sys/dev/dksubr.c:1.93	Thu Dec  8 12:22:56 2016
+++ src/sys/dev/dksubr.c	Thu Dec 22 13:42:14 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: dksubr.c,v 1.93 2016/12/08 12:22:56 mlelstv Exp $ */
+/* $NetBSD: dksubr.c,v 1.94 2016/12/22 13:42:14 mlelstv Exp $ */
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 1999, 2002, 2008 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dksubr.c,v 1.93 2016/12/08 12:22:56 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dksubr.c,v 1.94 2016/12/22 13:42:14 mlelstv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -378,9 +378,16 @@ dk_start(struct dk_softc *dksc, struct b
 	if (bp != NULL)
 		bufq_put(dksc->sc_bufq, bp);
 
-	if (dksc->sc_busy)
+	/*
+	 * If another thread is running the queue, increment
+	 * busy counter to 2 so that the queue is retried,
+	 * because the driver may now accept additional
+	 * requests.
+	 */
+	if (dksc->sc_busy < 2)
+		dksc->sc_busy++;
+	if (dksc->sc_busy > 1)
 		goto done;
-	dksc->sc_busy = true;
 
 	/*
 	 * Peeking at the buffer queue and committing the operation
@@ -393,34 +400,37 @@ dk_start(struct dk_softc *dksc, struct b
 	 * This keeps order of I/O operations, unlike bufq_put.
 	 */
 
-	bp = dksc->sc_deferred;
-	dksc->sc_deferred = NULL;
+	while (dksc->sc_busy > 0) {
 
-	if (bp == NULL)
-		bp = bufq_get(dksc->sc_bufq);
+		bp = dksc->sc_deferred;
+		dksc->sc_deferred = NULL;
 
-	while (bp != NULL) {
+		if (bp == NULL)
+			bp = bufq_get(dksc->sc_bufq);
 
-		disk_busy(&dksc->sc_dkdev);
-		mutex_exit(&dksc->sc_iolock);
-		error = dkd->d_diskstart(dksc->sc_dev, bp);
-		mutex_enter(&dksc->sc_iolock);
-		if (error == EAGAIN) {
-			dksc->sc_deferred = bp;
-			disk_unbusy(&dksc->sc_dkdev, 0, (bp->b_flags & B_READ));
-			break;
-		}
+		while (bp != NULL) {
+
+			disk_busy(&dksc->sc_dkdev);
+			mutex_exit(&dksc->sc_iolock);
+			error = dkd->d_diskstart(dksc->sc_dev, bp);
+			mutex_enter(&dksc->sc_iolock);
+			if (error == EAGAIN) {
+				dksc->sc_deferred = bp;
+				disk_unbusy(&dksc->sc_dkdev, 0, (bp->b_flags & B_READ));
+				break;
+			}
+
+			if (error != 0) {
+				bp->b_error = error;
+				bp->b_resid = bp->b_bcount;
+				dk_done1(dksc, bp, false);
+			}
 
-		if (error != 0) {
-			bp->b_error = error;
-			bp->b_resid = bp->b_bcount;
-			dk_done1(dksc, bp, false);
+			bp = bufq_get(dksc->sc_bufq);
 		}
 
-		bp = bufq_get(dksc->sc_bufq);
+		dksc->sc_busy--;
 	}
-
-	dksc->sc_busy = false;
 done:
 	mutex_exit(&dksc->sc_iolock);
 }

Index: src/sys/dev/dkvar.h
diff -u src/sys/dev/dkvar.h:1.27 src/sys/dev/dkvar.h:1.28
--- src/sys/dev/dkvar.h:1.27	Mon Oct 24 17:14:27 2016
+++ src/sys/dev/dkvar.h	Thu Dec 22 13:42:14 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: dkvar.h,v 1.27 2016/10/24 17:14:27 jdolecek Exp $ */
+/* $NetBSD: dkvar.h,v 1.28 2016/12/22 13:42:14 mlelstv Exp $ */
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -50,7 +50,7 @@ struct dk_softc {
 	struct bufq_state	*sc_bufq;	/* buffer queue */
 	int			 sc_dtype;	/* disk type */
 	struct buf		*sc_deferred;	/* retry after start failed */
-	bool			 sc_busy;	/* processing buffers */
+	int			 sc_busy;	/* processing buffers */
 	krndsource_t		 sc_rnd_source;	/* entropy source */
 };
 

Index: src/sys/sys/param.h
diff -u src/sys/sys/param.h:1.518 src/sys/sys/param.h:1.519
--- src/sys/sys/param.h:1.518	Fri Dec 16 23:37:21 2016
+++ src/sys/sys/param.h	Thu Dec 22 13:42:14 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: param.h,v 1.518 2016/12/16 23:37:21 riastradh Exp $	*/
+/*	$NetBSD: param.h,v 1.519 2016/12/22 13:42:14 mlelstv Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -67,7 +67,7 @@
  *	2.99.9		(299000900)
  */
 
-#define	__NetBSD_Version__	799005100	/* NetBSD 7.99.51 */
+#define	__NetBSD_Version__	799005200	/* NetBSD 7.99.52 */
 
 #define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
     (m) * 1000000) + (p) * 100) <= __NetBSD_Version__)

Reply via email to