From 6fcc47111ae14f284007e1b9a5002babb01d913c Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Wed, 7 Feb 2007 13:17:57 +0100 Subject: [SCSI] zfcp: Invalid locking order Invalid locking order. Kernel hangs after trying to take two locks which are dependend on each other. Introducing temporary variable to free requests. Free lock after requests are copied. Signed-off-by: Swen Schillig Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_ext.h | 2 +- drivers/s390/scsi/zfcp_fsf.c | 23 ++++++++++------------- 2 files changed, 11 insertions(+), 14 deletions(-) (limited to 'drivers/s390/scsi') diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index b8794d77285..7ec8e352b1f 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -89,7 +89,7 @@ extern int zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **, u32, u32, struct zfcp_sg_list *); extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long); extern void zfcp_erp_start_timer(struct zfcp_fsf_req *); -extern int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *); +extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *); extern int zfcp_fsf_status_read(struct zfcp_adapter *, int); extern int zfcp_fsf_req_create(struct zfcp_adapter *, u32, int, mempool_t *, unsigned long *, struct zfcp_fsf_req **); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 067f1519eb0..eabf86bb13f 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -176,28 +176,25 @@ static void zfcp_fsf_req_dismiss(struct zfcp_adapter *adapter, /** * zfcp_fsf_req_dismiss_all - dismiss all remaining fsf requests */ -int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) +void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) { struct zfcp_fsf_req *request, *tmp; unsigned long flags; + LIST_HEAD(remove_queue); unsigned int i, counter; spin_lock_irqsave(&adapter->req_list_lock, flags); atomic_set(&adapter->reqs_active, 0); - for (i=0; ireq_list[i])) - continue; - - counter = 0; - list_for_each_entry_safe(request, tmp, - &adapter->req_list[i], list) { - zfcp_fsf_req_dismiss(adapter, request, counter); - counter++; - } - } + for (i=0; ireq_list[i], &remove_queue); + spin_unlock_irqrestore(&adapter->req_list_lock, flags); - return 0; + counter = 0; + list_for_each_entry_safe(request, tmp, &remove_queue, list) { + zfcp_fsf_req_dismiss(adapter, request, counter); + counter++; + } } /* -- cgit v1.2.3