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__)