Adds deadline field to preserve the timeout on retries.  Calculates next
timeout for mod_timer correctly and uses an extra symbol, next_set, as
zero could be a valid 'next' value. Based off of timeout branch from Jens
git repo.

Signed-off-by: Malahal Naineni <[EMAIL PROTECTED]>

diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 79ed268..6bf31f0 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -259,6 +259,7 @@ static void rq_init(struct request_queue *q, struct request 
*rq)
        INIT_LIST_HEAD(&rq->timeout_list);
 
        rq->timeout = 0;
+       rq->deadline = 0;
        rq->errors = 0;
        rq->bio = rq->biotail = NULL;
        INIT_HLIST_NODE(&rq->hash);
@@ -3707,21 +3708,24 @@ static void blk_rq_timed_out(struct request *req)
 static void blk_rq_timed_out_timer(unsigned long data)
 {
        struct request_queue *q = (struct request_queue *) data;
-       unsigned long flags, next = 0;
+       unsigned long flags, next, next_set = 0;
        struct request *rq, *tmp;
 
        spin_lock_irqsave(q->queue_lock, flags);
 
        list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list) {
-               if (!next || time_before(next, rq->timeout))
-                       next = rq->timeout;
-               if (time_after_eq(jiffies, rq->timeout)) {
+               if (time_after_eq(jiffies, rq->deadline)) {
                        list_del_init(&rq->timeout_list);
                        blk_rq_timed_out(rq);
                }
+               if (!next_set) {
+                       next = rq->deadline;
+                       next_set = 1;
+               } else if (time_after(next, rq->deadline))
+                       next = rq->deadline;
        }
 
-       if (next)
+       if (next_set)
                mod_timer(&q->timeout, round_jiffies(next));
 
        spin_unlock_irqrestore(q->queue_lock, flags);
@@ -3760,9 +3764,9 @@ void blk_add_timer(struct request *req)
        BUG_ON(!list_empty(&req->timeout_list));
 
        if (req->timeout)
-               req->timeout += jiffies;
+               req->deadline = jiffies + req->timeout;
        else
-               req->timeout = jiffies + q->rq_timeout;
+               req->deadline = jiffies + q->rq_timeout;
 
        list_add_tail(&req->timeout_list, &q->timeout_list);
 
@@ -3771,7 +3775,7 @@ void blk_add_timer(struct request *req)
         * than an existing one, modify the timer. Round to next nearest
         * second.
         */
-       expiry = round_jiffies(req->timeout);
+       expiry = round_jiffies(req->deadline);
        if (!timer_pending(&q->timeout) ||
            time_before(expiry, q->timeout.expires))
                mod_timer(&q->timeout, expiry);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 917fe86..e495d61 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -295,7 +295,8 @@ struct request {
        void *data;
        void *sense;
 
-       unsigned long timeout;
+       unsigned long deadline;
+       unsigned int timeout;
        struct list_head timeout_list;
        int retries;
 
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to