aboutsummaryrefslogtreecommitdiffstats
path: root/block/blk-timeout.c
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2013-11-08 11:08:12 -0500
committerJens Axboe <axboe@kernel.dk>2013-11-08 11:08:12 -0500
commite37459b8e2c7db6735e39e019e448b76e5e77647 (patch)
treea3f0944db87a8ae0d41e5acbbbabc1e7ef534d1b /block/blk-timeout.c
parentc7d1ba417c7cb7297d14dd47a390ec90ce548d5c (diff)
parente7e245000110a7794de8f925b9edc06a9c852f80 (diff)
Merge branch 'blk-mq/core' into for-3.13/core
Signed-off-by: Jens Axboe <axboe@kernel.dk> Conflicts: block/blk-timeout.c
Diffstat (limited to 'block/blk-timeout.c')
-rw-r--r--block/blk-timeout.c74
1 files changed, 47 insertions, 27 deletions
diff --git a/block/blk-timeout.c b/block/blk-timeout.c
index abf725c655fc..bba81c9348e1 100644
--- a/block/blk-timeout.c
+++ b/block/blk-timeout.c
@@ -7,6 +7,7 @@
7#include <linux/fault-inject.h> 7#include <linux/fault-inject.h>
8 8
9#include "blk.h" 9#include "blk.h"
10#include "blk-mq.h"
10 11
11#ifdef CONFIG_FAIL_IO_TIMEOUT 12#ifdef CONFIG_FAIL_IO_TIMEOUT
12 13
@@ -88,10 +89,18 @@ static void blk_rq_timed_out(struct request *req)
88 ret = q->rq_timed_out_fn(req); 89 ret = q->rq_timed_out_fn(req);
89 switch (ret) { 90 switch (ret) {
90 case BLK_EH_HANDLED: 91 case BLK_EH_HANDLED:
91 __blk_complete_request(req); 92 /* Can we use req->errors here? */
93 if (q->mq_ops)
94 blk_mq_complete_request(req, req->errors);
95 else
96 __blk_complete_request(req);
92 break; 97 break;
93 case BLK_EH_RESET_TIMER: 98 case BLK_EH_RESET_TIMER:
94 blk_add_timer(req); 99 if (q->mq_ops)
100 blk_mq_add_timer(req);
101 else
102 blk_add_timer(req);
103
95 blk_clear_rq_complete(req); 104 blk_clear_rq_complete(req);
96 break; 105 break;
97 case BLK_EH_NOT_HANDLED: 106 case BLK_EH_NOT_HANDLED:
@@ -108,6 +117,23 @@ static void blk_rq_timed_out(struct request *req)
108 } 117 }
109} 118}
110 119
120void blk_rq_check_expired(struct request *rq, unsigned long *next_timeout,
121 unsigned int *next_set)
122{
123 if (time_after_eq(jiffies, rq->deadline)) {
124 list_del_init(&rq->timeout_list);
125
126 /*
127 * Check if we raced with end io completion
128 */
129 if (!blk_mark_rq_complete(rq))
130 blk_rq_timed_out(rq);
131 } else if (!*next_set || time_after(*next_timeout, rq->deadline)) {
132 *next_timeout = rq->deadline;
133 *next_set = 1;
134 }
135}
136
111void blk_rq_timed_out_timer(unsigned long data) 137void blk_rq_timed_out_timer(unsigned long data)
112{ 138{
113 struct request_queue *q = (struct request_queue *) data; 139 struct request_queue *q = (struct request_queue *) data;
@@ -117,21 +143,8 @@ void blk_rq_timed_out_timer(unsigned long data)
117 143
118 spin_lock_irqsave(q->queue_lock, flags); 144 spin_lock_irqsave(q->queue_lock, flags);
119 145
120 list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list) { 146 list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list)
121 if (time_after_eq(jiffies, rq->deadline)) { 147 blk_rq_check_expired(rq, &next, &next_set);
122 list_del_init(&rq->timeout_list);
123
124 /*
125 * Check if we raced with end io completion
126 */
127 if (blk_mark_rq_complete(rq))
128 continue;
129 blk_rq_timed_out(rq);
130 } else if (!next_set || time_after(next, rq->deadline)) {
131 next = rq->deadline;
132 next_set = 1;
133 }
134 }
135 148
136 if (next_set) 149 if (next_set)
137 mod_timer(&q->timeout, round_jiffies_up(next)); 150 mod_timer(&q->timeout, round_jiffies_up(next));
@@ -157,15 +170,7 @@ void blk_abort_request(struct request *req)
157} 170}
158EXPORT_SYMBOL_GPL(blk_abort_request); 171EXPORT_SYMBOL_GPL(blk_abort_request);
159 172
160/** 173void __blk_add_timer(struct request *req, struct list_head *timeout_list)
161 * blk_add_timer - Start timeout timer for a single request
162 * @req: request that is about to start running.
163 *
164 * Notes:
165 * Each request has its own timer, and as it is added to the queue, we
166 * set up the timer. When the request completes, we cancel the timer.
167 */
168void blk_add_timer(struct request *req)
169{ 174{
170 struct request_queue *q = req->q; 175 struct request_queue *q = req->q;
171 unsigned long expiry; 176 unsigned long expiry;
@@ -183,7 +188,8 @@ void blk_add_timer(struct request *req)
183 req->timeout = q->rq_timeout; 188 req->timeout = q->rq_timeout;
184 189
185 req->deadline = jiffies + req->timeout; 190 req->deadline = jiffies + req->timeout;
186 list_add_tail(&req->timeout_list, &q->timeout_list); 191 if (timeout_list)
192 list_add_tail(&req->timeout_list, timeout_list);
187 193
188 /* 194 /*
189 * If the timer isn't already pending or this timeout is earlier 195 * If the timer isn't already pending or this timeout is earlier
@@ -195,5 +201,19 @@ void blk_add_timer(struct request *req)
195 if (!timer_pending(&q->timeout) || 201 if (!timer_pending(&q->timeout) ||
196 time_before(expiry, q->timeout.expires)) 202 time_before(expiry, q->timeout.expires))
197 mod_timer(&q->timeout, expiry); 203 mod_timer(&q->timeout, expiry);
204
205}
206
207/**
208 * blk_add_timer - Start timeout timer for a single request
209 * @req: request that is about to start running.
210 *
211 * Notes:
212 * Each request has its own timer, and as it is added to the queue, we
213 * set up the timer. When the request completes, we cancel the timer.
214 */
215void blk_add_timer(struct request *req)
216{
217 __blk_add_timer(req, &req->q->timeout_list);
198} 218}
199 219