summaryrefslogtreecommitdiff
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
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@
-rw-r--r--sys/dev/softraid.c32
-rw-r--r--sys/dev/softraid_raid1.c97
-rw-r--r--sys/dev/softraidvar.h3
3 files changed, 51 insertions, 81 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;
diff --git a/sys/dev/softraid_raid1.c b/sys/dev/softraid_raid1.c
index 9479caf0b57..0e189930bfd 100644
--- a/sys/dev/softraid_raid1.c
+++ b/sys/dev/softraid_raid1.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraid_raid1.c,v 1.49 2013/03/31 15:44:52 jsing Exp $ */
+/* $OpenBSD: softraid_raid1.c,v 1.50 2013/04/21 13:00:21 jsing Exp $ */
/*
* Copyright (c) 2007 Marco Peereboom <marco@peereboom.us>
*
@@ -50,7 +50,7 @@ int sr_raid1_assemble(struct sr_discipline *, struct bioc_createraid *,
int, void *);
int sr_raid1_init(struct sr_discipline *sd);
int sr_raid1_rw(struct sr_workunit *);
-void sr_raid1_intr(struct buf *);
+int sr_raid1_wu_done(struct sr_workunit *);
void sr_raid1_set_chunk_state(struct sr_discipline *, int, int);
void sr_raid1_set_vol_state(struct sr_discipline *);
@@ -69,7 +69,7 @@ sr_raid1_discipline_init(struct sr_discipline *sd)
sd->sd_assemble = sr_raid1_assemble;
sd->sd_create = sr_raid1_create;
sd->sd_scsi_rw = sr_raid1_rw;
- sd->sd_scsi_intr = sr_raid1_intr;
+ sd->sd_scsi_wu_done = sr_raid1_wu_done;
sd->sd_set_chunk_state = sr_raid1_set_chunk_state;
sd->sd_set_vol_state = sr_raid1_set_vol_state;
}
@@ -429,81 +429,36 @@ bad:
return (1);
}
-void
-sr_raid1_intr(struct buf *bp)
+int
+sr_raid1_wu_done(struct sr_workunit *wu)
{
- struct sr_ccb *ccb = (struct sr_ccb *)bp;
- struct sr_workunit *wu = ccb->ccb_wu, *wup;
struct sr_discipline *sd = wu->swu_dis;
struct scsi_xfer *xs = wu->swu_xs;
- struct sr_softc *sc = sd->sd_sc;
- int s;
-
- DNPRINTF(SR_D_INTR, "%s: sr_intr bp %x xs %x\n",
- DEVNAME(sc), bp, xs);
-
- s = splbio();
-
- sr_ccb_done(ccb);
- DNPRINTF(SR_D_INTR, "%s: sr_intr: comp: %d count: %d failed: %d\n",
- DEVNAME(sc), wu->swu_ios_complete, wu->swu_io_count,
- wu->swu_ios_failed);
-
- if (wu->swu_ios_complete < wu->swu_io_count)
- goto done;
-
- xs->error = XS_NOERROR;
-
- /* if all ios failed, retry reads and give up on writes */
- if (wu->swu_ios_failed == wu->swu_ios_complete) {
- if (xs->flags & SCSI_DATA_IN) {
- printf("%s: retrying read on block %lld\n",
- DEVNAME(sc), ccb->ccb_buf.b_blkno);
- if (wu->swu_cb_active == 1)
- panic("%s: sr_raid1_intr_cb",
- DEVNAME(sd->sd_sc));
- sr_wu_release_ccbs(wu);
- wu->swu_state = SR_WU_RESTART;
- if (sd->sd_scsi_rw(wu) == 0)
- goto done;
- xs->error = XS_DRIVER_STUFFUP;
- } else {
- printf("%s: permanently failing write on block %lld\n",
- DEVNAME(sc), ccb->ccb_buf.b_blkno);
- xs->error = XS_DRIVER_STUFFUP;
- }
+ /* If at least one I/O succeeded, we are okay. */
+ if (wu->swu_ios_succeeded > 0) {
+ xs->error = XS_NOERROR;
+ return SR_WU_OK;
}
- TAILQ_FOREACH(wup, &sd->sd_wu_pendq, swu_link)
- if (wu == wup)
- break;
-
- if (wup == NULL)
- panic("%s: wu %p not on pending queue",
- DEVNAME(sd->sd_sc), wu);
-
- /* wu on pendq, remove */
- 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? */
- /* restart deferred wu */
- 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 all I/O failed, retry reads and give up on writes. */
+ if (xs->flags & SCSI_DATA_IN) {
+ printf("%s: retrying read on block %lld\n",
+ sd->sd_meta->ssd_devname, wu->swu_blk_start);
+ if (wu->swu_cb_active == 1)
+ panic("%s: sr_raid1_intr_cb",
+ DEVNAME(sd->sd_sc));
+ sr_wu_release_ccbs(wu);
+ wu->swu_state = SR_WU_RESTART;
+ if (sd->sd_scsi_rw(wu) == 0)
+ return SR_WU_RESTART;
+ } else {
+ printf("%s: permanently failing write on block %lld\n",
+ sd->sd_meta->ssd_devname, wu->swu_blk_start);
}
- if (wu->swu_flags & SR_WUF_REBUILD)
- wu->swu_flags |= SR_WUF_REBUILDIOCOMP;
- if (wu->swu_flags & SR_WUF_WAKEUP)
- wakeup(wu);
- if (!(wu->swu_flags & SR_WUF_REBUILD))
- sr_scsi_done(sd, xs);
+ wu->swu_state = SR_WU_FAILED;
+ xs->error = XS_DRIVER_STUFFUP;
-done:
- splx(s);
+ return SR_WU_FAILED;
}
diff --git a/sys/dev/softraidvar.h b/sys/dev/softraidvar.h
index 453fb58d4c5..ea0ad50d4c7 100644
--- a/sys/dev/softraidvar.h
+++ b/sys/dev/softraidvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraidvar.h,v 1.133 2013/03/31 11:37:40 jsing Exp $ */
+/* $OpenBSD: softraidvar.h,v 1.134 2013/04/21 13:00:21 jsing Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org>
@@ -599,6 +599,7 @@ struct sr_discipline {
struct scsi_sense_data sd_scsi_sense;
int (*sd_scsi_rw)(struct sr_workunit *);
void (*sd_scsi_intr)(struct buf *);
+ int (*sd_scsi_wu_done)(struct sr_workunit *);
void (*sd_scsi_done)(struct sr_workunit *);
int (*sd_scsi_sync)(struct sr_workunit *);
int (*sd_scsi_tur)(struct sr_workunit *);