aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSwen Schillig <swen@vnet.ibm.com>2007-02-07 07:17:57 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-02-10 14:11:14 -0500
commit6fcc47111ae14f284007e1b9a5002babb01d913c (patch)
tree71fbe20f7c69a7e93b239cc22a13bbc05936d024
parent19966769f9fc1968dcf5bffec2e53f7f40100872 (diff)
[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 <swen@vnet.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/s390/scsi/zfcp_ext.h2
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c23
2 files changed, 11 insertions, 14 deletions
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index b8794d77285d..7ec8e352b1fe 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 **,
89 u32, u32, struct zfcp_sg_list *); 89 u32, u32, struct zfcp_sg_list *);
90extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long); 90extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long);
91extern void zfcp_erp_start_timer(struct zfcp_fsf_req *); 91extern void zfcp_erp_start_timer(struct zfcp_fsf_req *);
92extern int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *); 92extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *);
93extern int zfcp_fsf_status_read(struct zfcp_adapter *, int); 93extern int zfcp_fsf_status_read(struct zfcp_adapter *, int);
94extern int zfcp_fsf_req_create(struct zfcp_adapter *, u32, int, mempool_t *, 94extern int zfcp_fsf_req_create(struct zfcp_adapter *, u32, int, mempool_t *,
95 unsigned long *, struct zfcp_fsf_req **); 95 unsigned long *, struct zfcp_fsf_req **);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 067f1519eb04..eabf86bb13f5 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,
176/** 176/**
177 * zfcp_fsf_req_dismiss_all - dismiss all remaining fsf requests 177 * zfcp_fsf_req_dismiss_all - dismiss all remaining fsf requests
178 */ 178 */
179int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) 179void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
180{ 180{
181 struct zfcp_fsf_req *request, *tmp; 181 struct zfcp_fsf_req *request, *tmp;
182 unsigned long flags; 182 unsigned long flags;
183 LIST_HEAD(remove_queue);
183 unsigned int i, counter; 184 unsigned int i, counter;
184 185
185 spin_lock_irqsave(&adapter->req_list_lock, flags); 186 spin_lock_irqsave(&adapter->req_list_lock, flags);
186 atomic_set(&adapter->reqs_active, 0); 187 atomic_set(&adapter->reqs_active, 0);
187 for (i=0; i<REQUEST_LIST_SIZE; i++) { 188 for (i=0; i<REQUEST_LIST_SIZE; i++)
188 if (list_empty(&adapter->req_list[i])) 189 list_splice_init(&adapter->req_list[i], &remove_queue);
189 continue; 190
190
191 counter = 0;
192 list_for_each_entry_safe(request, tmp,
193 &adapter->req_list[i], list) {
194 zfcp_fsf_req_dismiss(adapter, request, counter);
195 counter++;
196 }
197 }
198 spin_unlock_irqrestore(&adapter->req_list_lock, flags); 191 spin_unlock_irqrestore(&adapter->req_list_lock, flags);
199 192
200 return 0; 193 counter = 0;
194 list_for_each_entry_safe(request, tmp, &remove_queue, list) {
195 zfcp_fsf_req_dismiss(adapter, request, counter);
196 counter++;
197 }
201} 198}
202 199
203/* 200/*