summaryrefslogtreecommitdiff
path: root/sys/dev/softraid.c
diff options
context:
space:
mode:
authorJoel Sing <jsing@cvs.openbsd.org>2013-04-21 13:00:22 +0000
committerJoel Sing <jsing@cvs.openbsd.org>2013-04-21 13:00:22 +0000
commit1506227fb7bf0e35a5d09a78acdd4aba82ec2d9a (patch)
treecb3f0ca03efc81178a0a9aa59dcbcc5d23399060 /sys/dev/softraid.c
parent2a9984d3a338db73d4aaad8fc601709de644742e (diff)
Convert RAID1 to the new work unit completion functions and generic
interrupt handler. Disciplines such as RAID1/4/5/6 need a way to intercept I/O when the work unit is complete, but before the SCSI xfer is complete. This is provided via a sd_scsi_wu_done hook, which enables work units to be restarted or otherwise modified before the SCSI xfer completion occurs. ok krw@
Diffstat (limited to 'sys/dev/softraid.c')
-rw-r--r--sys/dev/softraid.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c
index 3a71a25c643..e75ca773d73 100644
--- a/sys/dev/softraid.c
+++ b/sys/dev/softraid.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraid.c,v 1.299 2013/03/31 15:46:11 jsing Exp $ */
+/* $OpenBSD: softraid.c,v 1.300 2013/04/21 13:00:21 jsing Exp $ */
/*
* Copyright (c) 2007, 2008, 2009 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org>
@@ -2255,36 +2255,49 @@ sr_wu_done_callback(void *arg1, void *arg2)
s = splbio();
+ if (wu->swu_ios_failed)
+ xs->error = XS_DRIVER_STUFFUP;
+ else
+ xs->error = XS_NOERROR;
+
+ if (sd->sd_scsi_wu_done) {
+ if (sd->sd_scsi_wu_done(wu) == SR_WU_RESTART)
+ goto done;
+ }
+
+ /* Remove work unit from pending queue. */
TAILQ_FOREACH(wup, &sd->sd_wu_pendq, swu_link)
if (wup == wu)
break;
-
if (wup == NULL)
panic("%s: wu %p not on pending queue",
DEVNAME(sd->sd_sc), wu);
-
TAILQ_REMOVE(&sd->sd_wu_pendq, wu, swu_link);
if (wu->swu_collider) {
+ if (wu->swu_ios_failed)
+ sr_raid_recreate_wu(wu->swu_collider);
+
+ /* XXX Should the collider be failed if this xs failed? */
wu->swu_collider->swu_state = SR_WU_INPROGRESS;
TAILQ_REMOVE(&sd->sd_wu_defq, wu->swu_collider, swu_link);
sr_raid_startwu(wu->swu_collider);
}
- if (wu->swu_ios_failed)
- xs->error = XS_DRIVER_STUFFUP;
- else
- xs->error = XS_NOERROR;
-
/*
* If a discipline provides its own sd_scsi_done function, then it
* is responsible for calling sr_scsi_done() once I/O is complete.
*/
+ if (wu->swu_flags & SR_WUF_REBUILD)
+ wu->swu_flags |= SR_WUF_REBUILDIOCOMP;
+ if (wu->swu_flags & SR_WUF_WAKEUP)
+ wakeup(wu);
if (sd->sd_scsi_done)
sd->sd_scsi_done(wu);
- else
+ else if (!(wu->swu_flags & SR_WUF_REBUILD))
sr_scsi_done(sd, xs);
+done:
splx(s);
}
@@ -3892,6 +3905,7 @@ sr_discipline_init(struct sr_discipline *sd, int level)
sd->sd_scsi_sync = sr_raid_sync;
sd->sd_scsi_rw = NULL;
sd->sd_scsi_intr = sr_raid_intr;
+ sd->sd_scsi_wu_done = NULL;
sd->sd_scsi_done = NULL;
sd->sd_set_chunk_state = sr_set_chunk_state;
sd->sd_set_vol_state = sr_set_vol_state;