diff options
| -rw-r--r-- | drivers/block/elevator.c | 43 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 3 |
2 files changed, 21 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) |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index a2e496f285a4..bd55b1df8997 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
| @@ -630,6 +630,9 @@ static inline void blkdev_dequeue_request(struct request *req) | |||
| 630 | static inline void elv_dispatch_add_tail(struct request_queue *q, | 630 | static inline void elv_dispatch_add_tail(struct request_queue *q, |
| 631 | struct request *rq) | 631 | struct request *rq) |
| 632 | { | 632 | { |
| 633 | if (q->last_merge == rq) | ||
| 634 | q->last_merge = NULL; | ||
| 635 | |||
| 633 | q->end_sector = rq_end_sector(rq); | 636 | q->end_sector = rq_end_sector(rq); |
| 634 | q->boundary_rq = rq; | 637 | q->boundary_rq = rq; |
| 635 | list_add_tail(&rq->queuelist, &q->queue_head); | 638 | list_add_tail(&rq->queuelist, &q->queue_head); |
