diff options
author | Tejun Heo <htejun@gmail.com> | 2005-10-20 10:46:23 -0400 |
---|---|---|
committer | Jens Axboe <axboe@nelson.home.kernel.dk> | 2005-10-28 02:45:20 -0400 |
commit | 06b86245c052963029bfd9020ca1f08ceb66f85a (patch) | |
tree | 1bd2675aceca74398f5fcf148f6cf2f551d63b52 /drivers/block | |
parent | b4878f245ec8e168cdd1f170f823a750b7dd4af5 (diff) |
[PATCH] 03/05 move last_merge handlin into generic elevator code
Currently, both generic elevator code and specific ioscheds
participate in the management and usage of last_merge. This
and the following patches move last_merge handling into
generic elevator code.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jens Axboe <axboe@suse.de>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/elevator.c | 43 |
1 files changed, 18 insertions, 25 deletions
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c index 29d6c8237ab3..415144372c75 100644 --- a/drivers/block/elevator.c +++ b/drivers/block/elevator.c | |||
@@ -83,15 +83,6 @@ inline int elv_try_merge(struct request *__rq, struct bio *bio) | |||
83 | } | 83 | } |
84 | EXPORT_SYMBOL(elv_try_merge); | 84 | EXPORT_SYMBOL(elv_try_merge); |
85 | 85 | ||
86 | inline int elv_try_last_merge(request_queue_t *q, struct bio *bio) | ||
87 | { | ||
88 | if (q->last_merge) | ||
89 | return elv_try_merge(q->last_merge, bio); | ||
90 | |||
91 | return ELEVATOR_NO_MERGE; | ||
92 | } | ||
93 | EXPORT_SYMBOL(elv_try_last_merge); | ||
94 | |||
95 | static struct elevator_type *elevator_find(const char *name) | 86 | static struct elevator_type *elevator_find(const char *name) |
96 | { | 87 | { |
97 | struct elevator_type *e = NULL; | 88 | struct elevator_type *e = NULL; |
@@ -239,6 +230,9 @@ void elv_dispatch_sort(request_queue_t *q, struct request *rq) | |||
239 | unsigned max_back; | 230 | unsigned max_back; |
240 | struct list_head *entry; | 231 | struct list_head *entry; |
241 | 232 | ||
233 | if (q->last_merge == rq) | ||
234 | q->last_merge = NULL; | ||
235 | |||
242 | boundary = q->end_sector; | 236 | boundary = q->end_sector; |
243 | max_back = q->max_back_kb * 2; | 237 | max_back = q->max_back_kb * 2; |
244 | boundary = boundary > max_back ? boundary - max_back : 0; | 238 | boundary = boundary > max_back ? boundary - max_back : 0; |
@@ -265,6 +259,15 @@ void elv_dispatch_sort(request_queue_t *q, struct request *rq) | |||
265 | int elv_merge(request_queue_t *q, struct request **req, struct bio *bio) | 259 | int elv_merge(request_queue_t *q, struct request **req, struct bio *bio) |
266 | { | 260 | { |
267 | elevator_t *e = q->elevator; | 261 | elevator_t *e = q->elevator; |
262 | int ret; | ||
263 | |||
264 | if (q->last_merge) { | ||
265 | ret = elv_try_merge(q->last_merge, bio); | ||
266 | if (ret != ELEVATOR_NO_MERGE) { | ||
267 | *req = q->last_merge; | ||
268 | return ret; | ||
269 | } | ||
270 | } | ||
268 | 271 | ||
269 | if (e->ops->elevator_merge_fn) | 272 | if (e->ops->elevator_merge_fn) |
270 | return e->ops->elevator_merge_fn(q, req, bio); | 273 | return e->ops->elevator_merge_fn(q, req, bio); |
@@ -278,6 +281,8 @@ void elv_merged_request(request_queue_t *q, struct request *rq) | |||
278 | 281 | ||
279 | if (e->ops->elevator_merged_fn) | 282 | if (e->ops->elevator_merged_fn) |
280 | e->ops->elevator_merged_fn(q, rq); | 283 | e->ops->elevator_merged_fn(q, rq); |
284 | |||
285 | q->last_merge = rq; | ||
281 | } | 286 | } |
282 | 287 | ||
283 | void elv_merge_requests(request_queue_t *q, struct request *rq, | 288 | void elv_merge_requests(request_queue_t *q, struct request *rq, |
@@ -285,11 +290,10 @@ void elv_merge_requests(request_queue_t *q, struct request *rq, | |||
285 | { | 290 | { |
286 | elevator_t *e = q->elevator; | 291 | elevator_t *e = q->elevator; |
287 | 292 | ||
288 | if (q->last_merge == next) | ||
289 | q->last_merge = NULL; | ||
290 | |||
291 | if (e->ops->elevator_merge_req_fn) | 293 | if (e->ops->elevator_merge_req_fn) |
292 | e->ops->elevator_merge_req_fn(q, rq, next); | 294 | e->ops->elevator_merge_req_fn(q, rq, next); |
295 | |||
296 | q->last_merge = rq; | ||
293 | } | 297 | } |
294 | 298 | ||
295 | void elv_requeue_request(request_queue_t *q, struct request *rq) | 299 | void elv_requeue_request(request_queue_t *q, struct request *rq) |
@@ -384,6 +388,8 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where, | |||
384 | BUG_ON(!blk_fs_request(rq)); | 388 | BUG_ON(!blk_fs_request(rq)); |
385 | rq->flags |= REQ_SORTED; | 389 | rq->flags |= REQ_SORTED; |
386 | q->elevator->ops->elevator_add_req_fn(q, rq); | 390 | q->elevator->ops->elevator_add_req_fn(q, rq); |
391 | if (q->last_merge == NULL && rq_mergeable(rq)) | ||
392 | q->last_merge = rq; | ||
387 | break; | 393 | break; |
388 | 394 | ||
389 | default: | 395 | default: |
@@ -462,9 +468,6 @@ struct request *elv_next_request(request_queue_t *q) | |||
462 | rq->flags |= REQ_STARTED; | 468 | rq->flags |= REQ_STARTED; |
463 | } | 469 | } |
464 | 470 | ||
465 | if (rq == q->last_merge) | ||
466 | q->last_merge = NULL; | ||
467 | |||
468 | if (!q->boundary_rq || q->boundary_rq == rq) { | 471 | if (!q->boundary_rq || q->boundary_rq == rq) { |
469 | q->end_sector = rq_end_sector(rq); | 472 | q->end_sector = rq_end_sector(rq); |
470 | q->boundary_rq = NULL; | 473 | q->boundary_rq = NULL; |
@@ -518,16 +521,6 @@ void elv_dequeue_request(request_queue_t *q, struct request *rq) | |||
518 | */ | 521 | */ |
519 | if (blk_account_rq(rq)) | 522 | if (blk_account_rq(rq)) |
520 | q->in_flight++; | 523 | q->in_flight++; |
521 | |||
522 | /* | ||
523 | * the main clearing point for q->last_merge is on retrieval of | ||
524 | * request by driver (it calls elv_next_request()), but it _can_ | ||
525 | * also happen here if a request is added to the queue but later | ||
526 | * deleted without ever being given to driver (merged with another | ||
527 | * request). | ||
528 | */ | ||
529 | if (rq == q->last_merge) | ||
530 | q->last_merge = NULL; | ||
531 | } | 524 | } |
532 | 525 | ||
533 | int elv_queue_empty(request_queue_t *q) | 526 | int elv_queue_empty(request_queue_t *q) |