summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBart Van Assche <bvanassche@acm.org>2013-08-14 15:37:08 +0000
committerRobert Love <robert.w.love@intel.com>2013-09-04 13:23:38 -0700
commit5d73bea2d3a004698d16ba5face89f0bef383e76 (patch)
treea652a9094b2f4bb3d9398bf3da3497c2af1c3f8f
parentb86788658be425a5454246a954721d9122d2b3d6 (diff)
downloadlinux-5d73bea2d3a004698d16ba5face89f0bef383e76.tar.gz
linux-5d73bea2d3a004698d16ba5face89f0bef383e76.tar.bz2
linux-5d73bea2d3a004698d16ba5face89f0bef383e76.zip
libfc: Protect ep->esb_stat changes via ex_lock
This patch avoids that the WARN_ON(!(ep->esb_stat & ESB_ST_SEQ_INIT)) statement in fc_seq_send_locked() gets triggered sporadically when running FCoE target code due to concurrent ep->esb_stat modifications. Signed-off-by: Bart Van Assche <bvanassche@acm.org> Cc: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: Robert Love <robert.w.love@intel.com>
-rw-r--r--drivers/scsi/libfc/fc_exch.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 7000203845bd..bc0aba4fabb4 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -988,6 +988,7 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport,
}
}
+ spin_lock_bh(&ep->ex_lock);
/*
* At this point, we have the exchange held.
* Find or create the sequence.
@@ -1015,11 +1016,11 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport,
* sending RSP, hence write request on other
* end never finishes.
*/
- spin_lock_bh(&ep->ex_lock);
sp->ssb_stat |= SSB_ST_RESP;
sp->id = fh->fh_seq_id;
- spin_unlock_bh(&ep->ex_lock);
} else {
+ spin_unlock_bh(&ep->ex_lock);
+
/* sequence/exch should exist */
reject = FC_RJT_SEQ_ID;
goto rel;
@@ -1030,6 +1031,7 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport,
if (f_ctl & FC_FC_SEQ_INIT)
ep->esb_stat |= ESB_ST_SEQ_INIT;
+ spin_unlock_bh(&ep->ex_lock);
fr_seq(fp) = sp;
out:
@@ -1479,8 +1481,11 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
f_ctl = ntoh24(fh->fh_f_ctl);
fr_seq(fp) = sp;
+
+ spin_lock_bh(&ep->ex_lock);
if (f_ctl & FC_FC_SEQ_INIT)
ep->esb_stat |= ESB_ST_SEQ_INIT;
+ spin_unlock_bh(&ep->ex_lock);
if (fc_sof_needs_ack(sof))
fc_seq_send_ack(sp, fp);