]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Tejun Heo <tj@kernel.org> |
2 | Subject: block: add timer on blkdev_dequeue_request() not elv_next_request() | |
3 | References: bnc#440076 | |
4 | ||
5 | Block queue supports two usage models - one where block driver peeks | |
6 | at the front of queue using elv_next_request(), processes it and | |
7 | finishes it and the other where block driver peeks at the front of | |
8 | queue, dequeue the request using blkdev_dequeue_request() and finishes | |
9 | it. The latter is more flexible as it allows the driver to process | |
10 | multiple commands concurrently. | |
11 | ||
12 | These two inconsistent usage models affect the block layer | |
13 | implementation confusing. For some, elv_next_request() is considered | |
14 | the issue point while others consider blkdev_dequeue_request() the | |
15 | issue point. | |
16 | ||
17 | Till now the inconsistency mostly affect only accounting, so it didn't | |
18 | really break anything seriously; however, with block layer timeout, | |
19 | this inconsistency hits hard. Block layer considers | |
20 | elv_next_request() the issue point and adds timer but SCSI layer | |
21 | thinks it was just peeking and when the request can't process the | |
22 | command right away, it's just left there without further processing. | |
23 | This makes the request dangling on the timer list and, when the timer | |
24 | goes off, the request which the SCSI layer and below think is still on | |
25 | the block queue ends up in the EH queue, causing various problems - EH | |
26 | hang (failed count goes over busy count and EH never wakes up), | |
27 | WARN_ON() and oopses as low level driver trying to handle the unknown | |
28 | command, etc. depending on the timing. | |
29 | ||
30 | As SCSI midlayer is the only user of block layer timer at the moment, | |
31 | moving blk_add_timer() to elv_dequeue_request() fixes the problem; | |
32 | however, this two usage models definitely need to be cleaned up in the | |
33 | future. | |
34 | ||
35 | Signed-off-by: Tejun Heo <tj@kernel.org> | |
36 | Signed-off-by: Tejun Heo <teheo@suse.de> | |
37 | --- | |
38 | block/elevator.c | 12 ++++++------ | |
39 | 1 file changed, 6 insertions(+), 6 deletions(-) | |
40 | ||
41 | --- a/block/elevator.c | |
42 | +++ b/block/elevator.c | |
43 | @@ -781,12 +781,6 @@ struct request *elv_next_request(struct | |
44 | */ | |
45 | rq->cmd_flags |= REQ_STARTED; | |
46 | blk_add_trace_rq(q, rq, BLK_TA_ISSUE); | |
47 | - | |
48 | - /* | |
49 | - * We are now handing the request to the hardware, | |
50 | - * add the timeout handler | |
51 | - */ | |
52 | - blk_add_timer(rq); | |
53 | } | |
54 | ||
55 | if (!q->boundary_rq || q->boundary_rq == rq) { | |
56 | @@ -858,6 +852,12 @@ void elv_dequeue_request(struct request_ | |
57 | */ | |
58 | if (blk_account_rq(rq)) | |
59 | q->in_flight++; | |
60 | + | |
61 | + /* | |
62 | + * We are now handing the request to the hardware, add the | |
63 | + * timeout handler. | |
64 | + */ | |
65 | + blk_add_timer(rq); | |
66 | } | |
67 | EXPORT_SYMBOL(elv_dequeue_request); | |
68 |