[SCSI] zfcp: Fix oops when port disappears
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@linux.vnet.ibm.com>
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index e7d0652..e8fbeae 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -486,10 +486,12 @@
*/
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_terminate_rport_io(struct fc_rport *rport)
{
- struct zfcp_port *port = rport->dd_data;
+ struct zfcp_port *port;
- zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL);
+ write_lock_irq(&zfcp_data.config_lock);
+ port = rport->dd_data;
+ if (port)
+ zfcp_port_get(port);
+ write_unlock_irq(&zfcp_data.config_lock);
+
+ 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_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)