Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=03513bccad33667ed738cfd96dc5757e539e0bdb
Commit:     03513bccad33667ed738cfd96dc5757e539e0bdb
Parent:     11ab244c9faead91683a12e4cb10d26b279bb4aa
Author:     Stefan Weinhuber <[EMAIL PROTECTED]>
AuthorDate: Tue Feb 19 15:29:27 2008 +0100
Committer:  Martin Schwidefsky <[EMAIL PROTECTED]>
CommitDate: Tue Feb 19 15:29:33 2008 +0100

    [S390] dasd: fix locking in __dasd_device_process_final_queue
    
    After setting the status of the cqr and releasing the lock for the
    block cqr queue, we call the cqr callback function, which will usually
    just trigger the dasd_block_tasklet. But when the tasklet is already
    running the cqr might be processed before we invoke the callback
    function. In rare cases the callback pointer may already be invalid
    by the time we want to call it, which will result in a panic.
    Solution: Call the callback function first and then release the lock.
    
    Signed-off-by: Stefan Weinhuber <[EMAIL PROTECTED]>
    Signed-off-by: Martin Schwidefsky <[EMAIL PROTECTED]>
---
 drivers/s390/block/dasd.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index d984e0f..ccf46c9 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1149,12 +1149,14 @@ static void __dasd_device_process_final_queue(struct 
dasd_device *device,
 {
        struct list_head *l, *n;
        struct dasd_ccw_req *cqr;
+       struct dasd_block *block;
 
        list_for_each_safe(l, n, final_queue) {
                cqr = list_entry(l, struct dasd_ccw_req, devlist);
                list_del_init(&cqr->devlist);
-               if (cqr->block)
-                       spin_lock_bh(&cqr->block->queue_lock);
+               block = cqr->block;
+               if (block)
+                       spin_lock_bh(&block->queue_lock);
                switch (cqr->status) {
                case DASD_CQR_SUCCESS:
                        cqr->status = DASD_CQR_DONE;
@@ -1172,15 +1174,13 @@ static void __dasd_device_process_final_queue(struct 
dasd_device *device,
                                    cqr, cqr->status);
                        BUG();
                }
-               if (cqr->block)
-                       spin_unlock_bh(&cqr->block->queue_lock);
                if (cqr->callback != NULL)
                        (cqr->callback)(cqr, cqr->callback_data);
+               if (block)
+                       spin_unlock_bh(&block->queue_lock);
        }
 }
 
-
-
 /*
  * Take a look at the first request on the ccw queue and check
  * if it reached its expire time. If so, terminate the IO.
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to