|
@@ -789,6 +789,20 @@ static inline void cfq_slice_expired(struct cfq_data *cfqd, int timed_out)
|
|
|
__cfq_slice_expired(cfqd, cfqq, timed_out);
|
|
|
}
|
|
|
|
|
|
+static int start_idle_class_timer(struct cfq_data *cfqd)
|
|
|
+{
|
|
|
+ unsigned long end = cfqd->last_end_request + CFQ_IDLE_GRACE;
|
|
|
+ unsigned long now = jiffies;
|
|
|
+
|
|
|
+ if (time_before(now, end) &&
|
|
|
+ time_after_eq(now, cfqd->last_end_request)) {
|
|
|
+ mod_timer(&cfqd->idle_class_timer, end);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Get next queue for service. Unless we have a queue preemption,
|
|
|
* we'll simply select the first cfqq in the service tree.
|
|
@@ -805,19 +819,14 @@ static struct cfq_queue *cfq_get_next_queue(struct cfq_data *cfqd)
|
|
|
cfqq = rb_entry(n, struct cfq_queue, rb_node);
|
|
|
|
|
|
if (cfq_class_idle(cfqq)) {
|
|
|
- unsigned long end;
|
|
|
-
|
|
|
/*
|
|
|
* if we have idle queues and no rt or be queues had
|
|
|
* pending requests, either allow immediate service if
|
|
|
* the grace period has passed or arm the idle grace
|
|
|
* timer
|
|
|
*/
|
|
|
- end = cfqd->last_end_request + CFQ_IDLE_GRACE;
|
|
|
- if (time_before(jiffies, end)) {
|
|
|
- mod_timer(&cfqd->idle_class_timer, end);
|
|
|
+ if (start_idle_class_timer(cfqd))
|
|
|
cfqq = NULL;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
return cfqq;
|
|
@@ -2036,17 +2045,14 @@ out_cont:
|
|
|
static void cfq_idle_class_timer(unsigned long data)
|
|
|
{
|
|
|
struct cfq_data *cfqd = (struct cfq_data *) data;
|
|
|
- unsigned long flags, end;
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
spin_lock_irqsave(cfqd->queue->queue_lock, flags);
|
|
|
|
|
|
/*
|
|
|
* race with a non-idle queue, reset timer
|
|
|
*/
|
|
|
- end = cfqd->last_end_request + CFQ_IDLE_GRACE;
|
|
|
- if (!time_after_eq(jiffies, end))
|
|
|
- mod_timer(&cfqd->idle_class_timer, end);
|
|
|
- else
|
|
|
+ if (!start_idle_class_timer(cfqd))
|
|
|
cfq_schedule_dispatch(cfqd);
|
|
|
|
|
|
spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
|