diff options
author | Hannes Reinecke <hare@suse.de> | 2016-05-24 08:11:58 +0200 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2016-07-13 05:16:31 +0200 |
commit | baa6719f902af9c03e528b08dfb847de295b5137 (patch) | |
tree | 8ac928054932e15da8feaa5a60b7385ab0787958 /drivers/scsi/fcoe/fcoe_ctlr.c | |
parent | scsi: ultrastor.c depends on ISA_DMA_API (diff) | |
download | linux-baa6719f902af9c03e528b08dfb847de295b5137.tar.xz linux-baa6719f902af9c03e528b08dfb847de295b5137.zip |
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/fcoe/fcoe_ctlr.c')
-rw-r--r-- | drivers/scsi/fcoe/fcoe_ctlr.c | 7 |
1 files changed, 1 insertions, 6 deletions
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 3e83d485f743..ada4bdec9a4c 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -2496,14 +2496,13 @@ static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *fip, u32 port_id, u8 *mac) struct fcoe_rport *frport; int ret = -1; - rcu_read_lock(); rdata = lport->tt.rport_lookup(lport, port_id); if (rdata) { frport = fcoe_ctlr_rport(rdata); memcpy(mac, frport->enode_mac, ETH_ALEN); ret = 0; + kref_put(&rdata->kref, lport->tt.rport_destroy); } - rcu_read_unlock(); return ret; } @@ -2585,11 +2584,7 @@ static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip, fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0); return; } - mutex_lock(&lport->disc.disc_mutex); rdata = lport->tt.rport_lookup(lport, new->ids.port_id); - if (rdata) - kref_get(&rdata->kref); - mutex_unlock(&lport->disc.disc_mutex); if (rdata) { if (rdata->ids.node_name == new->ids.node_name && rdata->ids.port_name == new->ids.port_name) { |