summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2009-12-03 14:31:04 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2009-12-03 14:31:04 +0000
commit36248a1ec61b88fe6a01f270d58658df81e36f54 (patch)
treefd2889b64491998f8d021db1ae9099327f0a69f0 /sys
parent5d60ca0fd0cb50ff9e57c9facd10a9f81565bb89 (diff)
prevent a completion interrupt pulling io of the buf queue and shoving it
down to the disk while a process is doing the same thing. this will avoid some relatively minor io reordering from occurring. discovered by krw@ during his long dark trek through the code. requested by marco@
Diffstat (limited to 'sys')
-rw-r--r--sys/scsi/sd.c18
-rw-r--r--sys/scsi/sdvar.h4
2 files changed, 19 insertions, 3 deletions
diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c
index 08378cbcc33..87a0133f647 100644
--- a/sys/scsi/sd.c
+++ b/sys/scsi/sd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sd.c,v 1.168 2009/12/03 06:09:30 dlg Exp $ */
+/* $OpenBSD: sd.c,v 1.169 2009/12/03 14:31:03 dlg Exp $ */
/* $NetBSD: sd.c,v 1.111 1997/04/02 02:29:41 mycroft Exp $ */
/*-
@@ -171,6 +171,7 @@ sdattach(struct device *parent, struct device *self, void *aux)
SC_DEBUG(sc_link, SDEV_DB2, ("sdattach:\n"));
mtx_init(&sd->sc_buf_mtx, IPL_BIO);
+ mtx_init(&sd->sc_start_mtx, IPL_BIO);
/*
* Store information needed to contact our base driver
@@ -691,6 +692,15 @@ sdstart(void *v)
SC_DEBUG(sc_link, SDEV_DB2, ("sdstart\n"));
+ mtx_enter(&sc->sc_start_mtx);
+ if (ISSET(sc->flags, SDF_STARTING)) {
+ mtx_leave(&sc->sc_start_mtx);
+ return;
+ }
+
+ SET(sc->flags, SDF_STARTING);
+ mtx_leave(&sc->sc_start_mtx);
+
CLR(sc->flags, SDF_WAITING);
while (!ISSET(sc->flags, SDF_WAITING) &&
(bp = sd_buf_dequeue(sc)) != NULL) {
@@ -710,7 +720,7 @@ sdstart(void *v)
xs = scsi_xs_get(link, SCSI_NOSLEEP);
if (xs == NULL) {
sd_buf_requeue(sc, bp);
- return;
+ break;
}
blkno =
@@ -755,6 +765,10 @@ sdstart(void *v)
scsi_xs_exec(xs);
}
+
+ mtx_enter(&sc->sc_start_mtx);
+ CLR(sc->flags, SDF_STARTING);
+ mtx_leave(&sc->sc_start_mtx);
}
void
diff --git a/sys/scsi/sdvar.h b/sys/scsi/sdvar.h
index d9b8d2837a6..115d3ee07be 100644
--- a/sys/scsi/sdvar.h
+++ b/sys/scsi/sdvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sdvar.h,v 1.24 2009/12/01 01:40:02 dlg Exp $ */
+/* $OpenBSD: sdvar.h,v 1.25 2009/12/03 14:31:03 dlg Exp $ */
/* $NetBSD: sdvar.h,v 1.7 1998/08/17 00:49:03 mycroft Exp $ */
/*-
@@ -61,6 +61,7 @@ struct sd_softc {
#define SDF_DIRTY 0x20 /* disk is dirty; needs cache flush */
#define SDF_DYING 0x40 /* dying, when deactivated */
#define SDF_WAITING 0x80 /* bus is busy, try again later */
+#define SDF_STARTING 0x100 /* sdstart is already running */
struct scsi_link *sc_link; /* contains our targ, lun, etc. */
struct disk_parms {
u_long heads; /* number of heads */
@@ -71,6 +72,7 @@ struct sd_softc {
daddr64_t disksize; /* total number sectors */
} params;
struct mutex sc_buf_mtx;
+ struct mutex sc_start_mtx;
struct buf sc_buf_queue;
void *sc_sdhook; /* our shutdown hook */
struct timeout sc_timeout;