Commit 70932935 authored by Christof Schmitt's avatar Christof Schmitt Committed by James Bottomley

[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: default avatarMartin Petermann <martin@linux.vnet.ibm.com>
Signed-off-by: default avatarChristof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 3869bb6e
...@@ -671,8 +671,7 @@ void zfcp_port_dequeue(struct zfcp_port *port) ...@@ -671,8 +671,7 @@ void zfcp_port_dequeue(struct zfcp_port *port)
list_del(&port->list); list_del(&port->list);
write_unlock_irq(&zfcp_data.config_lock); write_unlock_irq(&zfcp_data.config_lock);
if (port->rport) if (port->rport)
fc_remote_port_delete(port->rport); port->rport->dd_data = NULL;
port->rport = NULL;
zfcp_adapter_put(port->adapter); zfcp_adapter_put(port->adapter);
sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs); sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs);
device_unregister(&port->sysfs_device); device_unregister(&port->sysfs_device);
......
...@@ -172,12 +172,16 @@ static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id, ...@@ -172,12 +172,16 @@ static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id,
struct fsf_link_down_info *link_down) struct fsf_link_down_info *link_down)
{ {
struct zfcp_adapter *adapter = req->adapter; struct zfcp_adapter *adapter = req->adapter;
unsigned long flags;
if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED) if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
return; return;
atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
read_lock_irqsave(&zfcp_data.config_lock, flags);
zfcp_scsi_schedule_rports_block(adapter); zfcp_scsi_schedule_rports_block(adapter);
read_unlock_irqrestore(&zfcp_data.config_lock, flags);
if (!link_down) if (!link_down)
goto out; goto out;
......
...@@ -486,10 +486,12 @@ static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout) ...@@ -486,10 +486,12 @@ static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
*/ */
static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport) 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); 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); write_unlock_irq(&zfcp_data.config_lock);
} }
...@@ -503,9 +505,18 @@ static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport) ...@@ -503,9 +505,18 @@ static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport)
*/ */
static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) 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) static void zfcp_scsi_rport_register(struct zfcp_port *port)
...@@ -534,8 +545,10 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port) ...@@ -534,8 +545,10 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port)
static void zfcp_scsi_rport_block(struct zfcp_port *port) static void zfcp_scsi_rport_block(struct zfcp_port *port)
{ {
if (port->rport) struct fc_rport *rport = port->rport;
fc_remote_port_delete(port->rport);
if (rport)
fc_remote_port_delete(rport);
} }
void zfcp_scsi_schedule_rport_register(struct zfcp_port *port) void zfcp_scsi_schedule_rport_register(struct zfcp_port *port)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment