diff options
author | mav <mav@FreeBSD.org> | 2015-10-05 09:20:57 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2015-10-05 09:20:57 +0000 |
commit | 8c00f07d7f38cb3df4107179c257f7cfb4bb9b68 (patch) | |
tree | 966566f337996c1bf28a367973ce283e25da38f9 | |
parent | cb0cd525755a333609ecfe32cfbc2870f1354990 (diff) | |
download | FreeBSD-src-8c00f07d7f38cb3df4107179c257f7cfb4bb9b68.zip FreeBSD-src-8c00f07d7f38cb3df4107179c257f7cfb4bb9b68.tar.gz |
MFC r287816: Close potential race between datamove and HA failover.
-rw-r--r-- | sys/cam/ctl/ctl.c | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index 4499733..01cdf33 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -10952,6 +10952,7 @@ ctl_failover_lun(struct ctl_lun *lun) if (io->flags & CTL_FLAG_FROM_OTHER_SC) { if (io->flags & CTL_FLAG_IO_ACTIVE) { io->flags |= CTL_FLAG_ABORT; + io->flags |= CTL_FLAG_FAILOVER; } else { /* This can be only due to DATAMOVE */ io->msg_type = CTL_MSG_DATAMOVE_DONE; io->flags |= CTL_FLAG_IO_ACTIVE; @@ -12104,12 +12105,14 @@ ctl_datamove_timer_wakeup(void *arg) void ctl_datamove(union ctl_io *io) { + struct ctl_lun *lun; void (*fe_datamove)(union ctl_io *io); mtx_assert(&control_softc->ctl_lock, MA_NOTOWNED); CTL_DEBUG_PRINT(("ctl_datamove\n")); + lun = (struct ctl_lun *)io->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; #ifdef CTL_TIME_IO if ((time_uptime - io->io_hdr.start_time) > ctl_time_io_secs) { char str[256]; @@ -12150,9 +12153,6 @@ ctl_datamove(union ctl_io *io) if (io->io_hdr.flags & CTL_FLAG_DELAY_DONE) { io->io_hdr.flags &= ~CTL_FLAG_DELAY_DONE; } else { - struct ctl_lun *lun; - - lun =(struct ctl_lun *)io->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; if ((lun != NULL) && (lun->delay_info.datamove_delay > 0)) { @@ -12328,7 +12328,24 @@ ctl_datamove(union ctl_io *io) msg.dt.sent_sg_entries = sg_entries_sent; } + + /* + * Officially handover the request from us to peer. + * If failover has just happened, then we must return error. + * If failover happen just after, then it is not our problem. + */ + if (lun) + mtx_lock(&lun->lun_lock); + if (io->io_hdr.flags & CTL_FLAG_FAILOVER) { + if (lun) + mtx_unlock(&lun->lun_lock); + io->io_hdr.port_status = 31342; + io->scsiio.be_move_done(io); + return; + } io->io_hdr.flags &= ~CTL_FLAG_IO_ACTIVE; + if (lun) + mtx_unlock(&lun->lun_lock); } else { /* |