diff options
-rw-r--r-- | block/cfq-iosched.c | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 15f7238f527f..a5de31f76d3b 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -172,6 +172,7 @@ struct cfq_data { | |||
172 | enum wl_prio_t serving_prio; | 172 | enum wl_prio_t serving_prio; |
173 | enum wl_type_t serving_type; | 173 | enum wl_type_t serving_type; |
174 | unsigned long workload_expires; | 174 | unsigned long workload_expires; |
175 | bool noidle_tree_requires_idle; | ||
175 | 176 | ||
176 | /* | 177 | /* |
177 | * Each priority tree is sorted by next_request position. These | 178 | * Each priority tree is sorted by next_request position. These |
@@ -1253,9 +1254,9 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) | |||
1253 | return; | 1254 | return; |
1254 | 1255 | ||
1255 | /* | 1256 | /* |
1256 | * still requests with the driver, don't idle | 1257 | * still active requests from this queue, don't idle |
1257 | */ | 1258 | */ |
1258 | if (rq_in_driver(cfqd)) | 1259 | if (cfqq->dispatched) |
1259 | return; | 1260 | return; |
1260 | 1261 | ||
1261 | /* | 1262 | /* |
@@ -1478,6 +1479,7 @@ static void choose_service_tree(struct cfq_data *cfqd) | |||
1478 | 1479 | ||
1479 | slice = max_t(unsigned, slice, CFQ_MIN_TT); | 1480 | slice = max_t(unsigned, slice, CFQ_MIN_TT); |
1480 | cfqd->workload_expires = jiffies + slice; | 1481 | cfqd->workload_expires = jiffies + slice; |
1482 | cfqd->noidle_tree_requires_idle = false; | ||
1481 | } | 1483 | } |
1482 | 1484 | ||
1483 | /* | 1485 | /* |
@@ -2597,17 +2599,27 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) | |||
2597 | cfq_clear_cfqq_slice_new(cfqq); | 2599 | cfq_clear_cfqq_slice_new(cfqq); |
2598 | } | 2600 | } |
2599 | /* | 2601 | /* |
2600 | * If there are no requests waiting in this queue, and | 2602 | * Idling is not enabled on: |
2601 | * there are other queues ready to issue requests, AND | 2603 | * - expired queues |
2602 | * those other queues are issuing requests within our | 2604 | * - idle-priority queues |
2603 | * mean seek distance, give them a chance to run instead | 2605 | * - async queues |
2604 | * of idling. | 2606 | * - queues with still some requests queued |
2607 | * - when there is a close cooperator | ||
2605 | */ | 2608 | */ |
2606 | if (cfq_slice_used(cfqq) || cfq_class_idle(cfqq)) | 2609 | if (cfq_slice_used(cfqq) || cfq_class_idle(cfqq)) |
2607 | cfq_slice_expired(cfqd, 1); | 2610 | cfq_slice_expired(cfqd, 1); |
2608 | else if (cfqq_empty && !cfq_close_cooperator(cfqd, cfqq) && | 2611 | else if (sync && cfqq_empty && |
2609 | sync && !rq_noidle(rq)) | 2612 | !cfq_close_cooperator(cfqd, cfqq)) { |
2610 | cfq_arm_slice_timer(cfqd); | 2613 | cfqd->noidle_tree_requires_idle |= !rq_noidle(rq); |
2614 | /* | ||
2615 | * Idling is enabled for SYNC_WORKLOAD. | ||
2616 | * SYNC_NOIDLE_WORKLOAD idles at the end of the tree | ||
2617 | * only if we processed at least one !rq_noidle request | ||
2618 | */ | ||
2619 | if (cfqd->serving_type == SYNC_WORKLOAD | ||
2620 | || cfqd->noidle_tree_requires_idle) | ||
2621 | cfq_arm_slice_timer(cfqd); | ||
2622 | } | ||
2611 | } | 2623 | } |
2612 | 2624 | ||
2613 | if (!rq_in_driver(cfqd)) | 2625 | if (!rq_in_driver(cfqd)) |