From b7f15f3c94196accac799727502ed88a029ae7ef Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Wed, 1 Oct 2008 12:42:22 +0200 Subject: [SCSI] zfcp: fix deadlock caused by shared work queue tasks Each adapter reopen trigger automatically a scan_port task which is waiting for the ERP to be finished before further processing. Since the initial device setup enqueues adapter, port and LUN which are individual ERP actions, this process would start after everything is done. Unfortunately the port_reopen requires another scheduled work to be finished which is queued after the automatic scan_port -> deadlock ! This fix creates an own work queue for ERP based nameserver requests. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index b998464..05f3de6 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -168,6 +168,8 @@ static int __init zfcp_module_init(void) if (!zfcp_data.gid_pn_cache) goto out_gid_cache; + zfcp_data.work_queue = create_singlethread_workqueue("zfcp_wq"); + INIT_LIST_HEAD(&zfcp_data.adapter_list_head); sema_init(&zfcp_data.config_sema, 1); rwlock_init(&zfcp_data.config_lock); diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 7fa8937..73eb415 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -602,6 +602,7 @@ struct zfcp_data { struct kmem_cache *fsf_req_qtcb_cache; struct kmem_cache *sr_buffer_cache; struct kmem_cache *gid_pn_cache; + struct workqueue_struct *work_queue; }; /* struct used by memory pools for fsf_requests */ diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 174b38f..f5ebeb7 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -869,7 +869,7 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) return zfcp_erp_open_ptp_port(act); if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) { - schedule_work(&port->gid_pn_work); + queue_work(zfcp_data.work_queue, &port->gid_pn_work); return ZFCP_ERP_CONTINUES; } case ZFCP_ERP_STEP_NAMESERVER_LOOKUP: @@ -1209,7 +1209,7 @@ static void zfcp_erp_schedule_work(struct zfcp_unit *unit) atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); INIT_WORK(&p->work, zfcp_erp_scsi_scan); p->unit = unit; - schedule_work(&p->work); + queue_work(zfcp_data.work_queue, &p->work); } static void zfcp_erp_rport_register(struct zfcp_port *port) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index f073fff..600ef57 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -329,7 +329,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) zfcp_fsf_req_free(req); atomic_inc(&adapter->stat_miss); - schedule_work(&adapter->stat_work); + queue_work(zfcp_data.work_queue, &adapter->stat_work); } static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req) -- cgit v0.10.2