summaryrefslogtreecommitdiff
path: root/drivers/scsi/libfc/fc_lport.c
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2016-05-24 08:11:58 +0200
committerMartin K. Petersen <martin.petersen@oracle.com>2016-07-12 23:16:31 -0400
commitbaa6719f902af9c03e528b08dfb847de295b5137 (patch)
tree8ac928054932e15da8feaa5a60b7385ab0787958 /drivers/scsi/libfc/fc_lport.c
parent7e1ee4412ca35b17e21159d85224e37e8f259311 (diff)
libfc: Update rport reference counting
Originally libfc would just be initializing the refcount to '1', and using the disc_mutex to synchronize if and when the final put should be happening. This has a race condition as the mutex might be delayed, causing other threads to access an invalid structure. This patch updates the rport reference counting to increase the reference every time 'rport_lookup' is called, and decreases the reference correspondingly. This removes the need to hold 'disc_mutex' when removing the structure, and avoids the above race condition. Signed-off-by: Hannes Reinecke <hare@suse.com> Acked-by: Vasu Dev <vasu.dev@intel.com> Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/libfc/fc_lport.c')
-rw-r--r--drivers/scsi/libfc/fc_lport.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index e01a29863c38..b9b44daff159 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -2090,7 +2090,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job)
struct fc_rport *rport;
struct fc_rport_priv *rdata;
int rc = -EINVAL;
- u32 did;
+ u32 did, tov;
job->reply->reply_payload_rcv_len = 0;
if (rsp)
@@ -2121,15 +2121,20 @@ int fc_lport_bsg_request(struct fc_bsg_job *job)
case FC_BSG_HST_CT:
did = ntoh24(job->request->rqst_data.h_ct.port_id);
- if (did == FC_FID_DIR_SERV)
+ if (did == FC_FID_DIR_SERV) {
rdata = lport->dns_rdata;
- else
+ if (!rdata)
+ break;
+ tov = rdata->e_d_tov;
+ } else {
rdata = lport->tt.rport_lookup(lport, did);
+ if (!rdata)
+ break;
+ tov = rdata->e_d_tov;
+ kref_put(&rdata->kref, lport->tt.rport_destroy);
+ }
- if (!rdata)
- break;
-
- rc = fc_lport_ct_request(job, lport, did, rdata->e_d_tov);
+ rc = fc_lport_ct_request(job, lport, did, tov);
break;
case FC_BSG_HST_ELS_NOLOGIN: