summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-10-05 09:20:57 +0000
committermav <mav@FreeBSD.org>2015-10-05 09:20:57 +0000
commit8c00f07d7f38cb3df4107179c257f7cfb4bb9b68 (patch)
tree966566f337996c1bf28a367973ce283e25da38f9
parentcb0cd525755a333609ecfe32cfbc2870f1354990 (diff)
downloadFreeBSD-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.c23
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 {
/*
OpenPOWER on IntegriCloud