aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorShaohua Li <shaohua.li@intel.com>2011-07-12 08:24:55 -0400
committerJens Axboe <jaxboe@fusionio.com>2011-07-12 08:24:55 -0400
commitf5f2b6ceb23e02ff35c6dbc6a39aa776ace99cda (patch)
tree19ea26a1832c03c1c221675d3372b86abd12cc83 /block
parent383cd7213f95a2784ab5038fe292844178768b82 (diff)
CFQ: add think time check for service tree
Currently when the last queue of a service tree has no request, we don't expire the queue to hope request from the service tree comes soon, so the service tree 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=10 direct=1 [test1] rw=randread ioengine=libaio size=500m directory=/mnt filename=file1 thinktime=9000 [test2] rw=read ioengine=libaio size=1G directory=/mnt filename=file2 patched base test1 41k/s 33k/s test2 15868k/s 15789k/s total 15902k/s 15817k/s A slightly better 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 has variation even without the patch, but the average throughput 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.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 56255599a022..baa90606f01a 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -87,9 +87,10 @@ struct cfq_rb_root {
87 unsigned count; 87 unsigned count;
88 unsigned total_weight; 88 unsigned total_weight;
89 u64 min_vdisktime; 89 u64 min_vdisktime;
90 struct cfq_ttime ttime;
90}; 91};
91#define CFQ_RB_ROOT (struct cfq_rb_root) { .rb = RB_ROOT, .left = NULL, \ 92#define CFQ_RB_ROOT (struct cfq_rb_root) { .rb = RB_ROOT, \
92 .count = 0, .min_vdisktime = 0, } 93 .ttime = {.last_end_request = jiffies,},}
93 94
94/* 95/*
95 * Per process-grouping structure 96 * Per process-grouping structure
@@ -391,6 +392,18 @@ CFQ_CFQQ_FNS(wait_busy);
391 j++, st = i < IDLE_WORKLOAD ? \ 392 j++, st = i < IDLE_WORKLOAD ? \
392 &cfqg->service_trees[i][j]: NULL) \ 393 &cfqg->service_trees[i][j]: NULL) \
393 394
395static inline bool cfq_io_thinktime_big(struct cfq_data *cfqd,
396 struct cfq_ttime *ttime, bool group_idle)
397{
398 unsigned long slice;
399 if (!sample_valid(ttime->ttime_samples))
400 return false;
401 if (group_idle)
402 slice = cfqd->cfq_group_idle;
403 else
404 slice = cfqd->cfq_slice_idle;
405 return ttime->ttime_mean > slice;
406}
394 407
395static inline bool iops_mode(struct cfq_data *cfqd) 408static inline bool iops_mode(struct cfq_data *cfqd)
396{ 409{
@@ -1955,7 +1968,8 @@ static bool cfq_should_idle(struct cfq_data *cfqd, struct cfq_queue *cfqq)
1955 * Otherwise, we do only if they are the last ones 1968 * Otherwise, we do only if they are the last ones
1956 * in their service tree. 1969 * in their service tree.
1957 */ 1970 */
1958 if (service_tree->count == 1 && cfq_cfqq_sync(cfqq)) 1971 if (service_tree->count == 1 && cfq_cfqq_sync(cfqq) &&
1972 !cfq_io_thinktime_big(cfqd, &service_tree->ttime, false))
1959 return true; 1973 return true;
1960 cfq_log_cfqq(cfqd, cfqq, "Not idling. st->count:%d", 1974 cfq_log_cfqq(cfqd, cfqq, "Not idling. st->count:%d",
1961 service_tree->count); 1975 service_tree->count);
@@ -3220,8 +3234,11 @@ static void
3220cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_queue *cfqq, 3234cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_queue *cfqq,
3221 struct cfq_io_context *cic) 3235 struct cfq_io_context *cic)
3222{ 3236{
3223 if (cfq_cfqq_sync(cfqq)) 3237 if (cfq_cfqq_sync(cfqq)) {
3224 __cfq_update_io_thinktime(&cic->ttime, cfqd->cfq_slice_idle); 3238 __cfq_update_io_thinktime(&cic->ttime, cfqd->cfq_slice_idle);
3239 __cfq_update_io_thinktime(&cfqq->service_tree->ttime,
3240 cfqd->cfq_slice_idle);
3241 }
3225} 3242}
3226 3243
3227static void 3244static void
@@ -3550,7 +3567,16 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
3550 cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--; 3567 cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--;
3551 3568
3552 if (sync) { 3569 if (sync) {
3570 struct cfq_rb_root *service_tree;
3571
3553 RQ_CIC(rq)->ttime.last_end_request = now; 3572 RQ_CIC(rq)->ttime.last_end_request = now;
3573
3574 if (cfq_cfqq_on_rr(cfqq))
3575 service_tree = cfqq->service_tree;
3576 else
3577 service_tree = service_tree_for(cfqq->cfqg,
3578 cfqq_prio(cfqq), cfqq_type(cfqq));
3579 service_tree->ttime.last_end_request = now;
3554 if (!time_after(rq->start_time + cfqd->cfq_fifo_expire[1], now)) 3580 if (!time_after(rq->start_time + cfqd->cfq_fifo_expire[1], now))
3555 cfqd->last_delayed_sync = now; 3581 cfqd->last_delayed_sync = now;
3556 } 3582 }