aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoe Eykholt <jeykholt@cisco.com>2010-03-12 19:07:46 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-04-11 10:23:34 -0400
commit2f2ac4a0df8c4beee6e4057a69fa973b6040a573 (patch)
tree2ff71d9b1f13ff9cc0ed120725f68f003d7b9ae7
parent4dc7ccf7e9d9bca1989b840be9e8e84911387cf2 (diff)
[SCSI] libfc: fix oops in point-to-point mode
In point-to-point mode, if the PLOGI to the remote port times out, it can get deleted by the remote port module. Since there's no reference by the local port, lport->ptp_data points to a freed rport, and when the local port is reset and tries to logout again, an oops occurs in mutex_lock_nested(). Hold a reference count on the point-to-point rdata. Signed-off-by: Joe Eykholt <jeykholt@cisco.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r--drivers/scsi/libfc/fc_lport.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index d126ecfff704..fe8700f4326a 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -228,9 +228,12 @@ static void fc_lport_ptp_setup(struct fc_lport *lport,
228 u64 remote_wwnn) 228 u64 remote_wwnn)
229{ 229{
230 mutex_lock(&lport->disc.disc_mutex); 230 mutex_lock(&lport->disc.disc_mutex);
231 if (lport->ptp_rdata) 231 if (lport->ptp_rdata) {
232 lport->tt.rport_logoff(lport->ptp_rdata); 232 lport->tt.rport_logoff(lport->ptp_rdata);
233 kref_put(&lport->ptp_rdata->kref, lport->tt.rport_destroy);
234 }
233 lport->ptp_rdata = lport->tt.rport_create(lport, remote_fid); 235 lport->ptp_rdata = lport->tt.rport_create(lport, remote_fid);
236 kref_get(&lport->ptp_rdata->kref);
234 lport->ptp_rdata->ids.port_name = remote_wwpn; 237 lport->ptp_rdata->ids.port_name = remote_wwpn;
235 lport->ptp_rdata->ids.node_name = remote_wwnn; 238 lport->ptp_rdata->ids.node_name = remote_wwnn;
236 mutex_unlock(&lport->disc.disc_mutex); 239 mutex_unlock(&lport->disc.disc_mutex);
@@ -947,7 +950,11 @@ static void fc_lport_reset_locked(struct fc_lport *lport)
947 if (lport->dns_rdata) 950 if (lport->dns_rdata)
948 lport->tt.rport_logoff(lport->dns_rdata); 951 lport->tt.rport_logoff(lport->dns_rdata);
949 952
950 lport->ptp_rdata = NULL; 953 if (lport->ptp_rdata) {
954 lport->tt.rport_logoff(lport->ptp_rdata);
955 kref_put(&lport->ptp_rdata->kref, lport->tt.rport_destroy);
956 lport->ptp_rdata = NULL;
957 }
951 958
952 lport->tt.disc_stop(lport); 959 lport->tt.disc_stop(lport);
953 960