diff options
author | Shaohua Li <shaohua.li@intel.com> | 2011-07-12 08:24:56 -0400 |
---|---|---|
committer | Jens Axboe <jaxboe@fusionio.com> | 2011-07-12 08:24:56 -0400 |
commit | 7700fc4f675fa38094e78e345b594363a2fd895b (patch) | |
tree | 000ae1fb3d825240b7e78ad8d3db66be168ffe94 /block | |
parent | f5f2b6ceb23e02ff35c6dbc6a39aa776ace99cda (diff) |
CFQ: add think time check for group
Currently when the last queue of a group has no request, we don't expire
the queue to hope request from the group comes soon, so the group doesn't
miss its share. But if the think time is big, the assumption isn't correct
and we just waste bandwidth. In such case, we don't do idle.
[global]
runtime=30
direct=1
[test1]
cgroup=test1
cgroup_weight=1000
rw=randread
ioengine=libaio
size=500m
runtime=30
directory=/mnt
filename=file1
thinktime=9000
[test2]
cgroup=test2
cgroup_weight=1000
rw=randread
ioengine=libaio
size=500m
runtime=30
directory=/mnt
filename=file2
patched base
test1 64k 39k
test2 548k 540k
total 604k 578k
group1 gets much better throughput because it waits less time.
To check if the patch changes behavior of queue without think time. I also
tried to give test1 2ms think time or no think time. The test result is stable.
The thoughput doesn't change with/without the patch.
Signed-off-by: Shaohua Li <shaohua.li@intel.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/cfq-iosched.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index baa90606f01a..1f96ad6254f1 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -211,6 +211,7 @@ struct cfq_group { | |||
211 | #endif | 211 | #endif |
212 | /* number of requests that are on the dispatch list or inside driver */ | 212 | /* number of requests that are on the dispatch list or inside driver */ |
213 | int dispatched; | 213 | int dispatched; |
214 | struct cfq_ttime ttime; | ||
214 | }; | 215 | }; |
215 | 216 | ||
216 | /* | 217 | /* |
@@ -1067,6 +1068,8 @@ static struct cfq_group * cfq_alloc_cfqg(struct cfq_data *cfqd) | |||
1067 | *st = CFQ_RB_ROOT; | 1068 | *st = CFQ_RB_ROOT; |
1068 | RB_CLEAR_NODE(&cfqg->rb_node); | 1069 | RB_CLEAR_NODE(&cfqg->rb_node); |
1069 | 1070 | ||
1071 | cfqg->ttime.last_end_request = jiffies; | ||
1072 | |||
1070 | /* | 1073 | /* |
1071 | * Take the initial reference that will be released on destroy | 1074 | * Take the initial reference that will be released on destroy |
1072 | * This can be thought of a joint reference by cgroup and | 1075 | * This can be thought of a joint reference by cgroup and |
@@ -2381,8 +2384,9 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd) | |||
2381 | * this group, wait for requests to complete. | 2384 | * this group, wait for requests to complete. |
2382 | */ | 2385 | */ |
2383 | check_group_idle: | 2386 | check_group_idle: |
2384 | if (cfqd->cfq_group_idle && cfqq->cfqg->nr_cfqq == 1 | 2387 | if (cfqd->cfq_group_idle && cfqq->cfqg->nr_cfqq == 1 && |
2385 | && cfqq->cfqg->dispatched) { | 2388 | cfqq->cfqg->dispatched && |
2389 | !cfq_io_thinktime_big(cfqd, &cfqq->cfqg->ttime, true)) { | ||
2386 | cfqq = NULL; | 2390 | cfqq = NULL; |
2387 | goto keep_queue; | 2391 | goto keep_queue; |
2388 | } | 2392 | } |
@@ -3239,6 +3243,9 @@ cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
3239 | __cfq_update_io_thinktime(&cfqq->service_tree->ttime, | 3243 | __cfq_update_io_thinktime(&cfqq->service_tree->ttime, |
3240 | cfqd->cfq_slice_idle); | 3244 | cfqd->cfq_slice_idle); |
3241 | } | 3245 | } |
3246 | #ifdef CONFIG_CFQ_GROUP_IOSCHED | ||
3247 | __cfq_update_io_thinktime(&cfqq->cfqg->ttime, cfqd->cfq_group_idle); | ||
3248 | #endif | ||
3242 | } | 3249 | } |
3243 | 3250 | ||
3244 | static void | 3251 | static void |
@@ -3521,6 +3528,10 @@ static bool cfq_should_wait_busy(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
3521 | if (cfqq->cfqg->nr_cfqq > 1) | 3528 | if (cfqq->cfqg->nr_cfqq > 1) |
3522 | return false; | 3529 | return false; |
3523 | 3530 | ||
3531 | /* the only queue in the group, but think time is big */ | ||
3532 | if (cfq_io_thinktime_big(cfqd, &cfqq->cfqg->ttime, true)) | ||
3533 | return false; | ||
3534 | |||
3524 | if (cfq_slice_used(cfqq)) | 3535 | if (cfq_slice_used(cfqq)) |
3525 | return true; | 3536 | return true; |
3526 | 3537 | ||
@@ -3581,6 +3592,10 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) | |||
3581 | cfqd->last_delayed_sync = now; | 3592 | cfqd->last_delayed_sync = now; |
3582 | } | 3593 | } |
3583 | 3594 | ||
3595 | #ifdef CONFIG_CFQ_GROUP_IOSCHED | ||
3596 | cfqq->cfqg->ttime.last_end_request = now; | ||
3597 | #endif | ||
3598 | |||
3584 | /* | 3599 | /* |
3585 | * If this is the active queue, check if it needs to be expired, | 3600 | * If this is the active queue, check if it needs to be expired, |
3586 | * or if we want to idle in case it has no pending requests. | 3601 | * or if we want to idle in case it has no pending requests. |