[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>
This commit is contained in:
parent
3869bb6e73
commit
70932935b6
3 changed files with 24 additions and 8 deletions
|
@ -671,8 +671,7 @@ void zfcp_port_dequeue(struct zfcp_port *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);
|
||||
|
|
|
@ -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 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;
|
||||
|
|
|
@ -486,9 +486,11 @@ 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)
|
||||
{
|
||||
struct zfcp_port *port = rport->dd_data;
|
||||
struct zfcp_port *port;
|
||||
|
||||
write_lock_irq(&zfcp_data.config_lock);
|
||||
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_callbk(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);
|
||||
|
||||
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(struct zfcp_port *port)
|
|||
|
||||
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)
|
||||
|
|
Loading…
Reference in a new issue