[patch 15/15] zfcp: Fix oops when port disappears

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Christof Schmitt <christof.schmitt@xxxxxxxxxx>

The zfcp_port might have been removed, while the FC fast_io_fail timer
is still running and could trigger the terminate_rport_io callback.
Set the pointer to the zfcp_port to NULL and check accordingly
before using it.

Reviewed-by: Martin Petermann <martin@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Christof Schmitt <christof.schmitt@xxxxxxxxxx>
---
 drivers/s390/scsi/zfcp_aux.c  |    3 +--
 drivers/s390/scsi/zfcp_fsf.c  |    4 ++++
 drivers/s390/scsi/zfcp_scsi.c |   25 +++++++++++++++++++------
 3 files changed, 24 insertions(+), 8 deletions(-)

--- a/drivers/s390/scsi/zfcp_aux.c	2009-04-17 15:03:37.000000000 +0200
+++ b/drivers/s390/scsi/zfcp_aux.c	2009-04-17 15:04:00.000000000 +0200
@@ -671,8 +671,7 @@ void zfcp_port_dequeue(struct zfcp_port 
 	list_del(&port->list);
 	write_unlock_irq(&zfcp_data.config_lock);
 	if (port->rport)
-		fc_remote_port_delete(port->rport);
-	port->rport = NULL;
+		port->rport->dd_data = NULL;
 	zfcp_adapter_put(port->adapter);
 	sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs);
 	device_unregister(&port->sysfs_device);
--- a/drivers/s390/scsi/zfcp_scsi.c	2009-04-17 15:03:49.000000000 +0200
+++ b/drivers/s390/scsi/zfcp_scsi.c	2009-04-17 15:04:00.000000000 +0200
@@ -486,10 +486,12 @@ static void zfcp_set_rport_dev_loss_tmo(
  */
 static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport)
 {
-	struct zfcp_port *port = rport->dd_data;
+	struct zfcp_port *port;
 
 	write_lock_irq(&zfcp_data.config_lock);
-	port->rport = NULL;
+	port = rport->dd_data;
+	if (port)
+		port->rport = NULL;
 	write_unlock_irq(&zfcp_data.config_lock);
 }
 
@@ -503,9 +505,18 @@ static void zfcp_scsi_dev_loss_tmo_callb
  */
 static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
 {
-	struct zfcp_port *port = rport->dd_data;
+	struct zfcp_port *port;
+
+	write_lock_irq(&zfcp_data.config_lock);
+	port = rport->dd_data;
+	if (port)
+		zfcp_port_get(port);
+	write_unlock_irq(&zfcp_data.config_lock);
 
-	zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL);
+	if (port) {
+		zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL);
+		zfcp_port_put(port);
+	}
 }
 
 static void zfcp_scsi_rport_register(struct zfcp_port *port)
@@ -534,8 +545,10 @@ static void zfcp_scsi_rport_register(str
 
 static void zfcp_scsi_rport_block(struct zfcp_port *port)
 {
-	if (port->rport)
-		fc_remote_port_delete(port->rport);
+	struct fc_rport *rport = port->rport;
+
+	if (rport)
+		fc_remote_port_delete(rport);
 }
 
 void zfcp_scsi_schedule_rport_register(struct zfcp_port *port)
--- a/drivers/s390/scsi/zfcp_fsf.c	2009-04-17 15:03:52.000000000 +0200
+++ b/drivers/s390/scsi/zfcp_fsf.c	2009-04-17 15:04:00.000000000 +0200
@@ -172,12 +172,16 @@ static void zfcp_fsf_link_down_info_eval
 					 struct fsf_link_down_info *link_down)
 {
 	struct zfcp_adapter *adapter = req->adapter;
+	unsigned long flags;
 
 	if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
 		return;
 
 	atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
+
+	read_lock_irqsave(&zfcp_data.config_lock, flags);
 	zfcp_scsi_schedule_rports_block(adapter);
+	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 
 	if (!link_down)
 		goto out;

--
To unsubscribe from this list: send the line "unsubscribe linux-s390" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Kernel Development]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Info]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Linux Media]     [Device Mapper]

  Powered by Linux