|
@@ -172,6 +172,7 @@ struct cfq_data {
|
|
enum wl_prio_t serving_prio;
|
|
enum wl_prio_t serving_prio;
|
|
enum wl_type_t serving_type;
|
|
enum wl_type_t serving_type;
|
|
unsigned long workload_expires;
|
|
unsigned long workload_expires;
|
|
|
|
+ bool noidle_tree_requires_idle;
|
|
|
|
|
|
/*
|
|
/*
|
|
* Each priority tree is sorted by next_request position. These
|
|
* Each priority tree is sorted by next_request position. These
|
|
@@ -1253,9 +1254,9 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
|
|
return;
|
|
return;
|
|
|
|
|
|
/*
|
|
/*
|
|
- * still requests with the driver, don't idle
|
|
|
|
|
|
+ * still active requests from this queue, don't idle
|
|
*/
|
|
*/
|
|
- if (rq_in_driver(cfqd))
|
|
|
|
|
|
+ if (cfqq->dispatched)
|
|
return;
|
|
return;
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1478,6 +1479,7 @@ static void choose_service_tree(struct cfq_data *cfqd)
|
|
|
|
|
|
slice = max_t(unsigned, slice, CFQ_MIN_TT);
|
|
slice = max_t(unsigned, slice, CFQ_MIN_TT);
|
|
cfqd->workload_expires = jiffies + slice;
|
|
cfqd->workload_expires = jiffies + slice;
|
|
|
|
+ cfqd->noidle_tree_requires_idle = false;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -2597,17 +2599,27 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
|
|
cfq_clear_cfqq_slice_new(cfqq);
|
|
cfq_clear_cfqq_slice_new(cfqq);
|
|
}
|
|
}
|
|
/*
|
|
/*
|
|
- * If there are no requests waiting in this queue, and
|
|
|
|
- * there are other queues ready to issue requests, AND
|
|
|
|
- * those other queues are issuing requests within our
|
|
|
|
- * mean seek distance, give them a chance to run instead
|
|
|
|
- * of idling.
|
|
|
|
|
|
+ * Idling is not enabled on:
|
|
|
|
+ * - expired queues
|
|
|
|
+ * - idle-priority queues
|
|
|
|
+ * - async queues
|
|
|
|
+ * - queues with still some requests queued
|
|
|
|
+ * - when there is a close cooperator
|
|
*/
|
|
*/
|
|
if (cfq_slice_used(cfqq) || cfq_class_idle(cfqq))
|
|
if (cfq_slice_used(cfqq) || cfq_class_idle(cfqq))
|
|
cfq_slice_expired(cfqd, 1);
|
|
cfq_slice_expired(cfqd, 1);
|
|
- else if (cfqq_empty && !cfq_close_cooperator(cfqd, cfqq) &&
|
|
|
|
- sync && !rq_noidle(rq))
|
|
|
|
- cfq_arm_slice_timer(cfqd);
|
|
|
|
|
|
+ else if (sync && cfqq_empty &&
|
|
|
|
+ !cfq_close_cooperator(cfqd, cfqq)) {
|
|
|
|
+ cfqd->noidle_tree_requires_idle |= !rq_noidle(rq);
|
|
|
|
+ /*
|
|
|
|
+ * Idling is enabled for SYNC_WORKLOAD.
|
|
|
|
+ * SYNC_NOIDLE_WORKLOAD idles at the end of the tree
|
|
|
|
+ * only if we processed at least one !rq_noidle request
|
|
|
|
+ */
|
|
|
|
+ if (cfqd->serving_type == SYNC_WORKLOAD
|
|
|
|
+ || cfqd->noidle_tree_requires_idle)
|
|
|
|
+ cfq_arm_slice_timer(cfqd);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
if (!rq_in_driver(cfqd))
|
|
if (!rq_in_driver(cfqd))
|