aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorVasu Dev <vasu.dev@intel.com>2011-05-16 19:45:51 -0400
committerJames Bottomley <jbottomley@parallels.com>2011-05-24 12:37:15 -0400
commit0a219edb263ef93e4fd7a83804bea667e72a7bfa (patch)
tree4449e7bd98c46f3ab888a9ec7faedbc42e782024 /drivers
parent8d23f4ba38f399a6169613c6f158e39691aa694f (diff)
[SCSI] libfc: fix race in SRR response
In this case fsp was freed before error handler was invoked, this is fixed by having SRR fsp reference freed by exch destructor so that fsp will be always held until it exch is freed. Also don't reset fsp->recov_seq since this is needed by SRR error handler to do exch done. Signed-off-by: Vasu Dev <vasu.dev@intel.com> Tested-by: Ross Brattain <ross.b.brattain@intel.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <jbottomley@parallels.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/libfc/fc_fcp.c11
1 files changed, 4 insertions, 7 deletions
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index f880d40d4e78..57704e814681 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1673,7 +1673,8 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
1673 FC_FCTL_REQ, 0); 1673 FC_FCTL_REQ, 0);
1674 1674
1675 rec_tov = get_fsp_rec_tov(fsp); 1675 rec_tov = get_fsp_rec_tov(fsp);
1676 seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, NULL, 1676 seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp,
1677 fc_fcp_pkt_destroy,
1677 fsp, jiffies_to_msecs(rec_tov)); 1678 fsp, jiffies_to_msecs(rec_tov));
1678 if (!seq) 1679 if (!seq)
1679 goto retry; 1680 goto retry;
@@ -1720,7 +1721,6 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
1720 return; 1721 return;
1721 } 1722 }
1722 1723
1723 fsp->recov_seq = NULL;
1724 switch (fc_frame_payload_op(fp)) { 1724 switch (fc_frame_payload_op(fp)) {
1725 case ELS_LS_ACC: 1725 case ELS_LS_ACC:
1726 fsp->recov_retry = 0; 1726 fsp->recov_retry = 0;
@@ -1732,10 +1732,9 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
1732 break; 1732 break;
1733 } 1733 }
1734 fc_fcp_unlock_pkt(fsp); 1734 fc_fcp_unlock_pkt(fsp);
1735 fsp->lp->tt.exch_done(seq);
1736out: 1735out:
1736 fsp->lp->tt.exch_done(seq);
1737 fc_frame_free(fp); 1737 fc_frame_free(fp);
1738 fc_fcp_pkt_release(fsp); /* drop hold for outstanding SRR */
1739} 1738}
1740 1739
1741/** 1740/**
@@ -1747,8 +1746,6 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
1747{ 1746{
1748 if (fc_fcp_lock_pkt(fsp)) 1747 if (fc_fcp_lock_pkt(fsp))
1749 goto out; 1748 goto out;
1750 fsp->lp->tt.exch_done(fsp->recov_seq);
1751 fsp->recov_seq = NULL;
1752 switch (PTR_ERR(fp)) { 1749 switch (PTR_ERR(fp)) {
1753 case -FC_EX_TIMEOUT: 1750 case -FC_EX_TIMEOUT:
1754 if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) 1751 if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
@@ -1764,7 +1761,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
1764 } 1761 }
1765 fc_fcp_unlock_pkt(fsp); 1762 fc_fcp_unlock_pkt(fsp);
1766out: 1763out:
1767 fc_fcp_pkt_release(fsp); /* drop hold for outstanding SRR */ 1764 fsp->lp->tt.exch_done(fsp->recov_seq);
1768} 1765}
1769 1766
1770/** 1767/**