[SCSI] zfcp: Invalid locking order
authorSwen Schillig <swen@vnet.ibm.com>
Wed, 7 Feb 2007 12:17:57 +0000 (13:17 +0100)
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>
Sat, 10 Feb 2007 19:11:14 +0000 (13:11 -0600)
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>
drivers/s390/scsi/zfcp_ext.h
drivers/s390/scsi/zfcp_fsf.c

index b8794d7..7ec8e35 100644 (file)
@@ -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 **);
index 067f151..eabf86b 100644 (file)
@@ -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; i<REQUEST_LIST_SIZE; i++) {
-               if (list_empty(&adapter->req_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; i<REQUEST_LIST_SIZE; i++)
+               list_splice_init(&adapter->req_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++;
+       }
 }
 
 /*