diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2013-04-21 13:00:22 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2013-04-21 13:00:22 +0000 |
commit | 1506227fb7bf0e35a5d09a78acdd4aba82ec2d9a (patch) | |
tree | cb3f0ca03efc81178a0a9aa59dcbcc5d23399060 | |
parent | 2a9984d3a338db73d4aaad8fc601709de644742e (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.c | 32 | ||||
-rw-r--r-- | sys/dev/softraid_raid1.c | 97 | ||||
-rw-r--r-- | sys/dev/softraidvar.h | 3 |
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 *); |