Merge tag 'staging-4.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[cascardo/linux.git] / block / blk-timeout.c
index aa40aa9..a30441a 100644 (file)
@@ -127,13 +127,16 @@ static void blk_rq_check_expired(struct request *rq, unsigned long *next_timeout
        }
 }
 
-void blk_rq_timed_out_timer(unsigned long data)
+void blk_timeout_work(struct work_struct *work)
 {
-       struct request_queue *q = (struct request_queue *) data;
+       struct request_queue *q =
+               container_of(work, struct request_queue, timeout_work);
        unsigned long flags, next = 0;
        struct request *rq, *tmp;
        int next_set = 0;
 
+       if (blk_queue_enter(q, true))
+               return;
        spin_lock_irqsave(q->queue_lock, flags);
 
        list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list)
@@ -143,6 +146,7 @@ void blk_rq_timed_out_timer(unsigned long data)
                mod_timer(&q->timeout, round_jiffies_up(next));
 
        spin_unlock_irqrestore(q->queue_lock, flags);
+       blk_queue_exit(q);
 }
 
 /**
@@ -186,15 +190,13 @@ unsigned long blk_rq_timeout(unsigned long timeout)
  * Notes:
  *    Each request has its own timer, and as it is added to the queue, we
  *    set up the timer. When the request completes, we cancel the timer.
+ *    Queue lock must be held for the non-mq case, mq case doesn't care.
  */
 void blk_add_timer(struct request *req)
 {
        struct request_queue *q = req->q;
        unsigned long expiry;
 
-       if (req->cmd_flags & REQ_NO_TIMEOUT)
-               return;
-
        /* blk-mq has its own handler, so we don't need ->rq_timed_out_fn */
        if (!q->mq_ops && !q->rq_timed_out_fn)
                return;
@@ -209,6 +211,11 @@ void blk_add_timer(struct request *req)
                req->timeout = q->rq_timeout;
 
        req->deadline = jiffies + req->timeout;
+
+       /*
+        * Only the non-mq case needs to add the request to a protected list.
+        * For the mq case we simply scan the tag map.
+        */
        if (!q->mq_ops)
                list_add_tail(&req->timeout_list, &req->q->timeout_list);