From 92d5193b467c68e8432d6878980621c787e735af Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Fri, 17 Apr 2009 15:08:04 +0200 Subject: [SCSI] zfcp: Dont block zfcp_wq with scan When running the scsi_scan from the zfcp workqueue and the target device does not respond, the zfcp workqueue can block until the scsi_scan hits a timeout. Move the work to the scsi host workqueue, since this one is also used for the scan from the SCSI midlayer. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_scsi.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers/s390/scsi/zfcp_scsi.c') diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 58201e1ae478..5b11386d70bb 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -583,6 +583,23 @@ void zfcp_scsi_rport_work(struct work_struct *work) } +void zfcp_scsi_scan(struct work_struct *work) +{ + struct zfcp_unit *unit = container_of(work, struct zfcp_unit, + scsi_work); + struct fc_rport *rport; + + flush_work(&unit->port->rport_work); + rport = unit->port->rport; + + if (rport && rport->port_state == FC_PORTSTATE_ONLINE) + scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, + scsilun_to_int((struct scsi_lun *) + &unit->fcp_lun), 0); + + zfcp_unit_put(unit); +} + struct fc_function_template zfcp_transport_functions = { .show_starget_port_id = 1, .show_starget_port_name = 1, -- cgit v1.2.1 From c6936e7f34383db2f5038dfa2f0c168ebc2920e5 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Fri, 17 Apr 2009 15:08:11 +0200 Subject: [SCSI] zfcp: Fix abort handler for completions in progress When the abort handler cannot find a pending FSF request, the request completion could just be running. This means we cannot return SUCCESS, since this would lead to call to scsi_done after exiting the SCSI error handler which is not allowed. Reviewed-by: Martin Petermann Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/s390/scsi/zfcp_scsi.c') diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 5b11386d70bb..e7d065209065 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -171,7 +171,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) write_unlock_irqrestore(&adapter->abort_lock, flags); zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, old_req_id); - return SUCCESS; + return FAILED; /* completion could be in progress */ } old_req->data = NULL; -- cgit v1.2.1 From 70932935b61ee3dcc5a419ec4c367feb2ff808e4 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Fri, 17 Apr 2009 15:08:15 +0200 Subject: [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 Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_scsi.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'drivers/s390/scsi/zfcp_scsi.c') diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index e7d065209065..e8fbeaeb5fbf 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -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) { - 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_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); - 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(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) -- cgit v1.2.1