diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2007-02-14 13:59:49 -0500 |
---|---|---|
committer | Jens Axboe <axboe@nelson.home.kernel.dk> | 2007-04-30 03:01:21 -0400 |
commit | 1e3335de05da3dfbe48b8caa03db1834a2133256 (patch) | |
tree | 3783ea1ef788f564a78754906dc508ac66595b75 /block/cfq-iosched.c | |
parent | b9099ff63c75216d6ca10bce5a1abcd9293c27e6 (diff) |
cfq-iosched: improve preemption for cooperating tasks
When testing the syslet async io approach, I discovered that CFQ
sometimes didn't perform as well as expected. cfq_should_preempt()
needs to better check for cooperating tasks, so fix that by allowing
preemption of an equal priority queue if the recently queued request
is as good a candidate for IO as the one we are currently waiting for.
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r-- | block/cfq-iosched.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index f92ba2a869b4..bfb396774cbb 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -867,15 +867,11 @@ static int cfq_arm_slice_timer(struct cfq_data *cfqd) | |||
867 | 867 | ||
868 | static void cfq_dispatch_insert(request_queue_t *q, struct request *rq) | 868 | static void cfq_dispatch_insert(request_queue_t *q, struct request *rq) |
869 | { | 869 | { |
870 | struct cfq_data *cfqd = q->elevator->elevator_data; | ||
871 | struct cfq_queue *cfqq = RQ_CFQQ(rq); | 870 | struct cfq_queue *cfqq = RQ_CFQQ(rq); |
872 | 871 | ||
873 | cfq_remove_request(rq); | 872 | cfq_remove_request(rq); |
874 | cfqq->on_dispatch[rq_is_sync(rq)]++; | 873 | cfqq->on_dispatch[rq_is_sync(rq)]++; |
875 | elv_dispatch_sort(q, rq); | 874 | elv_dispatch_sort(q, rq); |
876 | |||
877 | rq = list_entry(q->queue_head.prev, struct request, queuelist); | ||
878 | cfqd->last_sector = rq->sector + rq->nr_sectors; | ||
879 | } | 875 | } |
880 | 876 | ||
881 | /* | 877 | /* |
@@ -1585,6 +1581,7 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, | |||
1585 | struct request *rq) | 1581 | struct request *rq) |
1586 | { | 1582 | { |
1587 | struct cfq_queue *cfqq = cfqd->active_queue; | 1583 | struct cfq_queue *cfqq = cfqd->active_queue; |
1584 | sector_t dist; | ||
1588 | 1585 | ||
1589 | if (cfq_class_idle(new_cfqq)) | 1586 | if (cfq_class_idle(new_cfqq)) |
1590 | return 0; | 1587 | return 0; |
@@ -1594,14 +1591,14 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, | |||
1594 | 1591 | ||
1595 | if (cfq_class_idle(cfqq)) | 1592 | if (cfq_class_idle(cfqq)) |
1596 | return 1; | 1593 | return 1; |
1597 | if (!cfq_cfqq_wait_request(new_cfqq)) | 1594 | |
1598 | return 0; | ||
1599 | /* | 1595 | /* |
1600 | * if the new request is sync, but the currently running queue is | 1596 | * if the new request is sync, but the currently running queue is |
1601 | * not, let the sync request have priority. | 1597 | * not, let the sync request have priority. |
1602 | */ | 1598 | */ |
1603 | if (rq_is_sync(rq) && !cfq_cfqq_sync(cfqq)) | 1599 | if (rq_is_sync(rq) && !cfq_cfqq_sync(cfqq)) |
1604 | return 1; | 1600 | return 1; |
1601 | |||
1605 | /* | 1602 | /* |
1606 | * So both queues are sync. Let the new request get disk time if | 1603 | * So both queues are sync. Let the new request get disk time if |
1607 | * it's a metadata request and the current queue is doing regular IO. | 1604 | * it's a metadata request and the current queue is doing regular IO. |
@@ -1609,6 +1606,21 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, | |||
1609 | if (rq_is_meta(rq) && !cfqq->meta_pending) | 1606 | if (rq_is_meta(rq) && !cfqq->meta_pending) |
1610 | return 1; | 1607 | return 1; |
1611 | 1608 | ||
1609 | if (!cfqd->active_cic || !cfq_cfqq_wait_request(cfqq)) | ||
1610 | return 0; | ||
1611 | |||
1612 | /* | ||
1613 | * if this request is as-good as one we would expect from the | ||
1614 | * current cfqq, let it preempt | ||
1615 | */ | ||
1616 | if (rq->sector > cfqd->last_sector) | ||
1617 | dist = rq->sector - cfqd->last_sector; | ||
1618 | else | ||
1619 | dist = cfqd->last_sector - rq->sector; | ||
1620 | |||
1621 | if (dist <= cfqd->active_cic->seek_mean) | ||
1622 | return 1; | ||
1623 | |||
1612 | return 0; | 1624 | return 0; |
1613 | } | 1625 | } |
1614 | 1626 | ||
@@ -1719,6 +1731,8 @@ static void cfq_completed_request(request_queue_t *q, struct request *rq) | |||
1719 | cfqq->on_dispatch[sync]--; | 1731 | cfqq->on_dispatch[sync]--; |
1720 | cfqq->service_last = now; | 1732 | cfqq->service_last = now; |
1721 | 1733 | ||
1734 | cfqd->last_sector = rq->hard_sector + rq->hard_nr_sectors; | ||
1735 | |||
1722 | if (!cfq_class_idle(cfqq)) | 1736 | if (!cfq_class_idle(cfqq)) |
1723 | cfqd->last_end_request = now; | 1737 | cfqd->last_end_request = now; |
1724 | 1738 | ||