]>
Commit | Line | Data |
---|---|---|
1 | From: Tejun Heo <tj@kernel.org> | |
2 | Subject: block: internal dequeue shouldn't start timer | |
3 | References: bnc#449880 | |
4 | ||
5 | blkdev_dequeue_request() and elv_dequeue_request() are equivalent and | |
6 | both start the timeout timer. Barrier code dequeues the original | |
7 | barrier request but doesn't passes the request itself to lower level | |
8 | driver, only broken down proxy requests; however, as the original | |
9 | barrier code goes through the same dequeue path and timeout timer is | |
10 | started on it. If barrier sequence takes long enough, this timer | |
11 | expires but the low level driver has no idea about this request and | |
12 | oops follows. | |
13 | ||
14 | Timeout timer shouldn't have been started on the original barrier | |
15 | request as it never goes through actual IO. This patch unexports | |
16 | elv_dequeue_request(), which has no external user anyway, and makes it | |
17 | operate on elevator proper w/o adding the timer and make | |
18 | blkdev_dequeue_request() call elv_dequeue_request() and add timer. | |
19 | Internal users which don't pass the request to driver - barrier code | |
20 | and end_that_request_last() - are converted to use | |
21 | elv_dequeue_request(). | |
22 | ||
23 | Signed-off-by: Tejun Heo <tj@kernel.org> | |
24 | Cc: Mike Anderson <andmike@linux.vnet.ibm.com> | |
25 | Signed-off-by: Tejun Heo <teheo@suse.de> | |
26 | --- | |
27 | block/blk-barrier.c | 4 ++-- | |
28 | block/blk-core.c | 24 +++++++++++++++++++++++- | |
29 | block/elevator.c | 7 ------- | |
30 | include/linux/blkdev.h | 7 ++----- | |
31 | 4 files changed, 27 insertions(+), 15 deletions(-) | |
32 | ||
33 | --- a/block/blk-barrier.c | |
34 | +++ b/block/blk-barrier.c | |
35 | @@ -161,7 +161,7 @@ static inline struct request *start_orde | |
36 | /* | |
37 | * Prep proxy barrier request. | |
38 | */ | |
39 | - blkdev_dequeue_request(rq); | |
40 | + elv_dequeue_request(q, rq); | |
41 | q->orig_bar_rq = rq; | |
42 | rq = &q->bar_rq; | |
43 | blk_rq_init(q, rq); | |
44 | @@ -219,7 +219,7 @@ int blk_do_ordered(struct request_queue | |
45 | * This can happen when the queue switches to | |
46 | * ORDERED_NONE while this request is on it. | |
47 | */ | |
48 | - blkdev_dequeue_request(rq); | |
49 | + elv_dequeue_request(q, rq); | |
50 | if (__blk_end_request(rq, -EOPNOTSUPP, | |
51 | blk_rq_bytes(rq))) | |
52 | BUG(); | |
53 | --- a/block/blk-core.c | |
54 | +++ b/block/blk-core.c | |
55 | @@ -1536,6 +1536,28 @@ void submit_bio(int rw, struct bio *bio) | |
56 | EXPORT_SYMBOL(submit_bio); | |
57 | ||
58 | /** | |
59 | + * blkdev_dequeue_request - dequeue request and start timeout timer | |
60 | + * @req: request to dequeue | |
61 | + * | |
62 | + * Dequeue @req and start timeout timer on it. This hands off the | |
63 | + * request to the driver. | |
64 | + * | |
65 | + * Block internal functions which don't want to start timer should | |
66 | + * call elv_dequeue_request(). | |
67 | + */ | |
68 | +void blkdev_dequeue_request(struct request *req) | |
69 | +{ | |
70 | + elv_dequeue_request(req->q, req); | |
71 | + | |
72 | + /* | |
73 | + * We are now handing the request to the hardware, add the | |
74 | + * timeout handler. | |
75 | + */ | |
76 | + blk_add_timer(req); | |
77 | +} | |
78 | +EXPORT_SYMBOL(blkdev_dequeue_request); | |
79 | + | |
80 | +/** | |
81 | * __end_that_request_first - end I/O on a request | |
82 | * @req: the request being processed | |
83 | * @error: %0 for success, < %0 for error | |
84 | @@ -1670,7 +1692,7 @@ static void end_that_request_last(struct | |
85 | blk_queue_end_tag(req->q, req); | |
86 | ||
87 | if (blk_queued_rq(req)) | |
88 | - blkdev_dequeue_request(req); | |
89 | + elv_dequeue_request(req->q, req); | |
90 | ||
91 | if (unlikely(laptop_mode) && blk_fs_request(req)) | |
92 | laptop_io_completion(); | |
93 | --- a/block/elevator.c | |
94 | +++ b/block/elevator.c | |
95 | @@ -844,14 +844,7 @@ void elv_dequeue_request(struct request_ | |
96 | */ | |
97 | if (blk_account_rq(rq)) | |
98 | q->in_flight++; | |
99 | - | |
100 | - /* | |
101 | - * We are now handing the request to the hardware, add the | |
102 | - * timeout handler. | |
103 | - */ | |
104 | - blk_add_timer(rq); | |
105 | } | |
106 | -EXPORT_SYMBOL(elv_dequeue_request); | |
107 | ||
108 | int elv_queue_empty(struct request_queue *q) | |
109 | { | |
110 | --- a/include/linux/blkdev.h | |
111 | +++ b/include/linux/blkdev.h | |
112 | @@ -756,6 +756,8 @@ static inline void blk_run_address_space | |
113 | blk_run_backing_dev(mapping->backing_dev_info, NULL); | |
114 | } | |
115 | ||
116 | +extern void blkdev_dequeue_request(struct request *req); | |
117 | + | |
118 | /* | |
119 | * blk_end_request() and friends. | |
120 | * __blk_end_request() and end_request() must be called with | |
121 | @@ -790,11 +792,6 @@ extern void blk_abort_queue(struct reque | |
122 | extern unsigned int blk_rq_bytes(struct request *rq); | |
123 | extern unsigned int blk_rq_cur_bytes(struct request *rq); | |
124 | ||
125 | -static inline void blkdev_dequeue_request(struct request *req) | |
126 | -{ | |
127 | - elv_dequeue_request(req->q, req); | |
128 | -} | |
129 | - | |
130 | /* | |
131 | * Access functions for manipulating queue properties | |
132 | */ |