diff options
| -rw-r--r-- | block/cfq-iosched.c | 54 |
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 | ||
| 3273 | static 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 | |||
| 3259 | static void cfq_completed_request(struct request_queue *q, struct request *rq) | 3302 | static 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 | } |
