aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/cfq-iosched.c54
1 files changed, 48 insertions, 6 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index f41fdb5f3e0c..98b15b98b85d 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -2141,8 +2141,22 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
2141 /* 2141 /*
2142 * The active queue has run out of time, expire it and select new. 2142 * The active queue has run out of time, expire it and select new.
2143 */ 2143 */
2144 if (cfq_slice_used(cfqq) && !cfq_cfqq_must_dispatch(cfqq)) 2144 if (cfq_slice_used(cfqq) && !cfq_cfqq_must_dispatch(cfqq)) {
2145 goto expire; 2145 /*
2146 * If slice had not expired at the completion of last request
2147 * we might not have turned on wait_busy flag. Don't expire
2148 * the queue yet. Allow the group to get backlogged.
2149 *
2150 * The very fact that we have used the slice, that means we
2151 * have been idling all along on this queue and it should be
2152 * ok to wait for this request to complete.
2153 */
2154 if (cfqq->cfqg->nr_cfqq == 1 && cfqq->dispatched
2155 && cfq_should_idle(cfqd, cfqq))
2156 goto keep_queue;
2157 else
2158 goto expire;
2159 }
2146 2160
2147 /* 2161 /*
2148 * The active queue has requests and isn't expired, allow it to 2162 * The active queue has requests and isn't expired, allow it to
@@ -3256,6 +3270,35 @@ static void cfq_update_hw_tag(struct cfq_data *cfqd)
3256 cfqd->hw_tag = 0; 3270 cfqd->hw_tag = 0;
3257} 3271}
3258 3272
3273static bool cfq_should_wait_busy(struct cfq_data *cfqd, struct cfq_queue *cfqq)
3274{
3275 struct cfq_io_context *cic = cfqd->active_cic;
3276
3277 /* If there are other queues in the group, don't wait */
3278 if (cfqq->cfqg->nr_cfqq > 1)
3279 return false;
3280
3281 if (cfq_slice_used(cfqq))
3282 return true;
3283
3284 /* if slice left is less than think time, wait busy */
3285 if (cic && sample_valid(cic->ttime_samples)
3286 && (cfqq->slice_end - jiffies < cic->ttime_mean))
3287 return true;
3288
3289 /*
3290 * If think times is less than a jiffy than ttime_mean=0 and above
3291 * will not be true. It might happen that slice has not expired yet
3292 * but will expire soon (4-5 ns) during select_queue(). To cover the
3293 * case where think time is less than a jiffy, mark the queue wait
3294 * busy if only 1 jiffy is left in the slice.
3295 */
3296 if (cfqq->slice_end - jiffies == 1)
3297 return true;
3298
3299 return false;
3300}
3301
3259static void cfq_completed_request(struct request_queue *q, struct request *rq) 3302static void cfq_completed_request(struct request_queue *q, struct request *rq)
3260{ 3303{
3261 struct cfq_queue *cfqq = RQ_CFQQ(rq); 3304 struct cfq_queue *cfqq = RQ_CFQQ(rq);
@@ -3295,11 +3338,10 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
3295 } 3338 }
3296 3339
3297 /* 3340 /*
3298 * If this queue consumed its slice and this is last queue 3341 * Should we wait for next request to come in before we expire
3299 * in the group, wait for next request before we expire 3342 * the queue.
3300 * the queue
3301 */ 3343 */
3302 if (cfq_slice_used(cfqq) && cfqq->cfqg->nr_cfqq == 1) { 3344 if (cfq_should_wait_busy(cfqd, cfqq)) {
3303 cfqq->slice_end = jiffies + cfqd->cfq_slice_idle; 3345 cfqq->slice_end = jiffies + cfqd->cfq_slice_idle;
3304 cfq_mark_cfqq_wait_busy(cfqq); 3346 cfq_mark_cfqq_wait_busy(cfqq);
3305 } 3347 }