aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2005-11-01 03:23:49 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-02 00:58:06 -0500
commitca23509fbaac0ea662ab0e287bebb72f743f9e1f (patch)
treeb87f06d928e0ea06ae6244c1aeecf3e745f39bb9 /drivers
parent6c2af71f7f6ac10ab45e9461e1dd7aa09079643a (diff)
[PATCH] blk: fix dangling pointer access in __elv_add_request
cfq's add_req_fn callback may invoke q->request_fn directly and depending on low-level driver used and timing, a queued request may be finished & deallocated before add_req_fn callback returns. So, __elv_add_request must not access rq after it's passed to add_req_fn callback. This patch moves rq_mergeable test above add_req_fn(). This may result in q->last_merge pointing to REQ_NOMERGE request if add_req_fn callback sets it but as RQ_NOMERGE is checked again when blk layer actually tries to merge requests, this does not cause any problem. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/elevator.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index 36f1057084b0..d4a49a3df829 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -369,9 +369,14 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
369 case ELEVATOR_INSERT_SORT: 369 case ELEVATOR_INSERT_SORT:
370 BUG_ON(!blk_fs_request(rq)); 370 BUG_ON(!blk_fs_request(rq));
371 rq->flags |= REQ_SORTED; 371 rq->flags |= REQ_SORTED;
372 q->elevator->ops->elevator_add_req_fn(q, rq);
373 if (q->last_merge == NULL && rq_mergeable(rq)) 372 if (q->last_merge == NULL && rq_mergeable(rq))
374 q->last_merge = rq; 373 q->last_merge = rq;
374 /*
375 * Some ioscheds (cfq) run q->request_fn directly, so
376 * rq cannot be accessed after calling
377 * elevator_add_req_fn.
378 */
379 q->elevator->ops->elevator_add_req_fn(q, rq);
375 break; 380 break;
376 381
377 default: 382 default: