aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/cfq-iosched.c32
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))