Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Fix race condition in dksubr, where a dk_start from anot...



details:   https://anonhg.NetBSD.org/src/rev/c9404aabc977
branches:  trunk
changeset: 819905:c9404aabc977
user:      mlelstv <mlelstv%NetBSD.org@localhost>
date:      Thu Dec 22 13:42:14 2016 +0000

description:
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.

diffstat:

 sys/dev/dksubr.c |  62 ++++++++++++++++++++++++++++++++-----------------------
 sys/dev/dkvar.h  |   4 +-
 sys/sys/param.h  |   4 +-
 3 files changed, 40 insertions(+), 30 deletions(-)

diffs (133 lines):

diff -r 4b85e466a610 -r c9404aabc977 sys/dev/dksubr.c
--- a/sys/dev/dksubr.c  Thu Dec 22 13:26:24 2016 +0000
+++ b/sys/dev/dksubr.c  Thu Dec 22 13:42:14 2016 +0000
@@ -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 @@
        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 @@
         * This keeps order of I/O operations, unlike bufq_put.
         */
 
-       bp = dksc->sc_deferred;
-       dksc->sc_deferred = NULL;
+       while (dksc->sc_busy > 0) {
+
+               bp = dksc->sc_deferred;
+               dksc->sc_deferred = NULL;
 
-       if (bp == NULL)
-               bp = bufq_get(dksc->sc_bufq);
+               if (bp == NULL)
+                       bp = bufq_get(dksc->sc_bufq);
 
-       while (bp != NULL) {
+               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;
+                       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);
+                       }
+
+                       bp = bufq_get(dksc->sc_bufq);
                }
 
-               if (error != 0) {
-                       bp->b_error = error;
-                       bp->b_resid = bp->b_bcount;
-                       dk_done1(dksc, bp, false);
-               }
-
-               bp = bufq_get(dksc->sc_bufq);
+               dksc->sc_busy--;
        }
-
-       dksc->sc_busy = false;
 done:
        mutex_exit(&dksc->sc_iolock);
 }
diff -r 4b85e466a610 -r c9404aabc977 sys/dev/dkvar.h
--- a/sys/dev/dkvar.h   Thu Dec 22 13:26:24 2016 +0000
+++ b/sys/dev/dkvar.h   Thu Dec 22 13:42:14 2016 +0000
@@ -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 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 */
 };
 
diff -r 4b85e466a610 -r c9404aabc977 sys/sys/param.h
--- a/sys/sys/param.h   Thu Dec 22 13:26:24 2016 +0000
+++ b/sys/sys/param.h   Thu Dec 22 13:42:14 2016 +0000
@@ -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__)



Home | Main Index | Thread Index | Old Index