aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSwen Schillig <swen@vnet.ibm.com>2008-10-01 06:42:22 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-10-03 13:11:55 -0400
commitb7f15f3c94196accac799727502ed88a029ae7ef (patch)
treed620f4cc0fe75ca43b48a675fb7bd681cb7919f3 /drivers
parent57069386699994c3e67042fc4928c418f3a39e01 (diff)
[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 <swen@vnet.ibm.com> Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/s390/scsi/zfcp_aux.c2
-rw-r--r--drivers/s390/scsi/zfcp_def.h1
-rw-r--r--drivers/s390/scsi/zfcp_erp.c4
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c2
4 files changed, 6 insertions, 3 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index b9984648aca6..05f3de64f6a3 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)
168 if (!zfcp_data.gid_pn_cache) 168 if (!zfcp_data.gid_pn_cache)
169 goto out_gid_cache; 169 goto out_gid_cache;
170 170
171 zfcp_data.work_queue = create_singlethread_workqueue("zfcp_wq");
172
171 INIT_LIST_HEAD(&zfcp_data.adapter_list_head); 173 INIT_LIST_HEAD(&zfcp_data.adapter_list_head);
172 sema_init(&zfcp_data.config_sema, 1); 174 sema_init(&zfcp_data.config_sema, 1);
173 rwlock_init(&zfcp_data.config_lock); 175 rwlock_init(&zfcp_data.config_lock);
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 7fa8937c8c58..73eb41580f25 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -602,6 +602,7 @@ struct zfcp_data {
602 struct kmem_cache *fsf_req_qtcb_cache; 602 struct kmem_cache *fsf_req_qtcb_cache;
603 struct kmem_cache *sr_buffer_cache; 603 struct kmem_cache *sr_buffer_cache;
604 struct kmem_cache *gid_pn_cache; 604 struct kmem_cache *gid_pn_cache;
605 struct workqueue_struct *work_queue;
605}; 606};
606 607
607/* struct used by memory pools for fsf_requests */ 608/* 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 174b38fe7623..f5ebeb7ca2be 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)
869 if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) 869 if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP)
870 return zfcp_erp_open_ptp_port(act); 870 return zfcp_erp_open_ptp_port(act);
871 if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) { 871 if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) {
872 schedule_work(&port->gid_pn_work); 872 queue_work(zfcp_data.work_queue, &port->gid_pn_work);
873 return ZFCP_ERP_CONTINUES; 873 return ZFCP_ERP_CONTINUES;
874 } 874 }
875 case ZFCP_ERP_STEP_NAMESERVER_LOOKUP: 875 case ZFCP_ERP_STEP_NAMESERVER_LOOKUP:
@@ -1209,7 +1209,7 @@ static void zfcp_erp_schedule_work(struct zfcp_unit *unit)
1209 atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); 1209 atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
1210 INIT_WORK(&p->work, zfcp_erp_scsi_scan); 1210 INIT_WORK(&p->work, zfcp_erp_scsi_scan);
1211 p->unit = unit; 1211 p->unit = unit;
1212 schedule_work(&p->work); 1212 queue_work(zfcp_data.work_queue, &p->work);
1213} 1213}
1214 1214
1215static void zfcp_erp_rport_register(struct zfcp_port *port) 1215static 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 f073fff0868f..600ef5711acb 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)
329 zfcp_fsf_req_free(req); 329 zfcp_fsf_req_free(req);
330 330
331 atomic_inc(&adapter->stat_miss); 331 atomic_inc(&adapter->stat_miss);
332 schedule_work(&adapter->stat_work); 332 queue_work(zfcp_data.work_queue, &adapter->stat_work);
333} 333}
334 334
335static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req) 335static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req)