summaryrefslogtreecommitdiff
path: root/drivers/scsi/libfc/fc_lport.c
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2016-09-30 11:01:15 +0200
committerMartin K. Petersen <martin.petersen@oracle.com>2016-11-08 17:29:46 -0500
commita407c593398c886db4fa1fc5c6fec55e61187a09 (patch)
tree5428a0f043492514d1d3c0b6097a511f46967a29 /drivers/scsi/libfc/fc_lport.c
parent4d2095cc42a2d8062590891f929d9d694cbd927f (diff)
downloadlwn-a407c593398c886db4fa1fc5c6fec55e61187a09.tar.gz
lwn-a407c593398c886db4fa1fc5c6fec55e61187a09.zip
scsi: libfc: Fixup disc_mutex handling
The list of attached 'rdata' remote port structures is RCU protected, so there is no need to take the 'disc_mutex' when traversing it. Rather we should be using rcu_read_lock() and kref_get_unless_zero() to validate the entries. We need, however, take the disc_mutex when deleting an entry; otherwise we risk clashes with list_add. Signed-off-by: Hannes Reinecke <hare@suse.com> Acked-by: Johannes Thumshirn <jth@kernel.org> 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.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 04ce7cfb6d1b..4e11c90c783c 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -237,16 +237,19 @@ static const char *fc_lport_state(struct fc_lport *lport)
* @remote_fid: The FID of the ptp rport
* @remote_wwpn: The WWPN of the ptp rport
* @remote_wwnn: The WWNN of the ptp rport
+ *
+ * Locking Note: The lport lock is expected to be held before calling
+ * this routine.
*/
static void fc_lport_ptp_setup(struct fc_lport *lport,
u32 remote_fid, u64 remote_wwpn,
u64 remote_wwnn)
{
- mutex_lock(&lport->disc.disc_mutex);
if (lport->ptp_rdata) {
lport->tt.rport_logoff(lport->ptp_rdata);
kref_put(&lport->ptp_rdata->kref, lport->tt.rport_destroy);
}
+ mutex_lock(&lport->disc.disc_mutex);
lport->ptp_rdata = lport->tt.rport_create(lport, remote_fid);
kref_get(&lport->ptp_rdata->kref);
lport->ptp_rdata->ids.port_name = remote_wwpn;
@@ -1007,8 +1010,10 @@ EXPORT_SYMBOL(fc_lport_reset);
*/
static void fc_lport_reset_locked(struct fc_lport *lport)
{
- if (lport->dns_rdata)
+ if (lport->dns_rdata) {
lport->tt.rport_logoff(lport->dns_rdata);
+ lport->dns_rdata = NULL;
+ }
if (lport->ptp_rdata) {
lport->tt.rport_logoff(lport->ptp_rdata);