aboutsummaryrefslogtreecommitdiffstats
path: root/block/blk-timeout.c
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2009-04-23 04:32:59 -0400
committerJens Axboe <jens.axboe@oracle.com>2009-04-24 02:54:21 -0400
commit17d5c8ca7572124c9623045f24b0c21d4aa2b47f (patch)
treedfecc3aa2acae305c01238002a3e53d6ae8d3238 /block/blk-timeout.c
parentf3c737de8f57b5ce756010c2175f7d574194b30d (diff)
block: fix intermittent dm timeout based oops
Very rarely under stress testing of dm, oopses are occuring as something tampers with an old stack frame. This has been traced back to blk_abort_queue() leaving a timeout_list pointing to the stack. The reason is that sometimes blk_abort_request() won't delete the timer (if the request is marked as complete but before the timer has been removed, a small race window). Fix this by splicing back from the ususally empty list to the q->timeout_list. Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block/blk-timeout.c')
-rw-r--r--block/blk-timeout.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/block/blk-timeout.c b/block/blk-timeout.c
index 8f570c4c80ee..1ec0d503cacd 100644
--- a/block/blk-timeout.c
+++ b/block/blk-timeout.c
@@ -230,6 +230,13 @@ void blk_abort_queue(struct request_queue *q)
230 list_for_each_entry_safe(rq, tmp, &list, timeout_list) 230 list_for_each_entry_safe(rq, tmp, &list, timeout_list)
231 blk_abort_request(rq); 231 blk_abort_request(rq);
232 232
233 /*
234 * Occasionally, blk_abort_request() will return without
235 * deleting the element from the list. Make sure we add those back
236 * instead of leaving them on the local stack list.
237 */
238 list_splice(&list, &q->timeout_list);
239
233 spin_unlock_irqrestore(q->queue_lock, flags); 240 spin_unlock_irqrestore(q->queue_lock, flags);
234 241
235} 242}