diff options
author | Vasu Dev <vasu.dev@intel.com> | 2011-05-16 19:45:51 -0400 |
---|---|---|
committer | James Bottomley <jbottomley@parallels.com> | 2011-05-24 12:37:15 -0400 |
commit | 0a219edb263ef93e4fd7a83804bea667e72a7bfa (patch) | |
tree | 4449e7bd98c46f3ab888a9ec7faedbc42e782024 /drivers/scsi | |
parent | 8d23f4ba38f399a6169613c6f158e39691aa694f (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/scsi')
-rw-r--r-- | drivers/scsi/libfc/fc_fcp.c | 11 |
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); | ||
1736 | out: | 1735 | out: |
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); |
1766 | out: | 1763 | out: |
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 | /** |