Module Name:    src
Committed By:   jdolecek
Date:           Sat Oct 22 22:32:33 UTC 2016

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

Log Message:
change sc_deferred to TAILQ (reusing bufq b_actq) to avoid possible buf leak
for MPSAFE drivers


To generate a diff of this commit:
cvs rdiff -u -r1.89 -r1.90 src/sys/dev/dksubr.c
cvs rdiff -u -r1.25 -r1.26 src/sys/dev/dkvar.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.89 src/sys/dev/dksubr.c:1.90
--- src/sys/dev/dksubr.c:1.89	Wed Sep 14 23:05:05 2016
+++ src/sys/dev/dksubr.c	Sat Oct 22 22:32:33 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: dksubr.c,v 1.89 2016/09/14 23:05:05 mlelstv Exp $ */
+/* $NetBSD: dksubr.c,v 1.90 2016/10/22 22:32:33 jdolecek 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.89 2016/09/14 23:05:05 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dksubr.c,v 1.90 2016/10/22 22:32:33 jdolecek Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -105,6 +105,8 @@ dk_attach(struct dk_softc *dksc)
 	/* Attach the device into the rnd source list. */
 	rnd_attach_source(&dksc->sc_rnd_source, dksc->sc_xname,
 	    RND_TYPE_DISK, RND_FLAG_DEFAULT);
+
+	TAILQ_INIT(&dksc->sc_deferred);
 }
 
 void
@@ -378,25 +380,27 @@ dk_start(struct dk_softc *dksc, struct b
 	 *
 	 * So when a diskstart fails, the buffer is saved
 	 * and tried again before the next buffer is fetched.
-	 * dk_drain() handles flushing of a saved buffer.
+	 * dk_drain() handles flushing of a saved buffer(s).
 	 *
 	 * This keeps order of I/O operations, unlike bufq_put.
 	 */
 
-	bp = dksc->sc_deferred;
-	dksc->sc_deferred = NULL;
-
-	if (bp == NULL)
-		bp = bufq_get(dksc->sc_bufq);
-
-	while (bp != NULL) {
+	for(;;) {
+		bp = TAILQ_FIRST(&dksc->sc_deferred);
+		if (__predict_false(bp != NULL))
+			TAILQ_REMOVE(&dksc->sc_deferred, bp, b_actq);
+		else {
+			bp = bufq_get(dksc->sc_bufq);
+			if (bp == NULL)
+				break;
+		}
 
 		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;
+			TAILQ_INSERT_TAIL(&dksc->sc_deferred, bp, b_actq);
 			disk_unbusy(&dksc->sc_dkdev, 0, (bp->b_flags & B_READ));
 			break;
 		}
@@ -406,8 +410,6 @@ dk_start(struct dk_softc *dksc, struct b
 			bp->b_resid = bp->b_bcount;
 			dk_done1(dksc, bp, false);
 		}
-
-		bp = bufq_get(dksc->sc_bufq);
 	}
 
 	dksc->sc_busy = false;
@@ -451,9 +453,8 @@ dk_drain(struct dk_softc *dksc)
 	struct buf *bp;
 
 	mutex_enter(&dksc->sc_iolock);
-	bp = dksc->sc_deferred;
-	dksc->sc_deferred = NULL;
-	if (bp != NULL) {
+	while ((bp = TAILQ_FIRST(&dksc->sc_deferred)) != NULL) {
+		TAILQ_REMOVE(&dksc->sc_deferred, bp, b_actq);
 		bp->b_error = EIO;
 		bp->b_resid = bp->b_bcount;
 		biodone(bp); 

Index: src/sys/dev/dkvar.h
diff -u src/sys/dev/dkvar.h:1.25 src/sys/dev/dkvar.h:1.26
--- src/sys/dev/dkvar.h:1.25	Mon Dec 21 12:33:12 2015
+++ src/sys/dev/dkvar.h	Sat Oct 22 22:32:33 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: dkvar.h,v 1.25 2015/12/21 12:33:12 mlelstv Exp $ */
+/* $NetBSD: dkvar.h,v 1.26 2016/10/22 22:32:33 jdolecek Exp $ */
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -49,7 +49,7 @@ struct dk_softc {
 	kmutex_t		 sc_iolock;	/* protects buffer queue */
 	struct bufq_state	*sc_bufq;	/* buffer queue */
 	int			 sc_dtype;	/* disk type */
-	struct buf		*sc_deferred;	/* retry after start failed */
+	TAILQ_HEAD(, buf)	 sc_deferred;	/* retry after start failed */
 	bool			 sc_busy;	/* processing buffers */
 	krndsource_t		 sc_rnd_source;	/* entropy source */
 };

Reply via email to