cfq-iosched: idling on deep seeky sync queues
[linux-2.6-block.git] / block / cfq-iosched.c
index 2c1086acddfa4f91134bc40bf3cf44d14c63a785..15f7238f527f3f42e4a6ad327ee5cd8624eb6ad1 100644 (file)
@@ -260,6 +260,7 @@ enum cfqq_state_flags {
        CFQ_CFQQ_FLAG_slice_new,        /* no requests dispatched in slice */
        CFQ_CFQQ_FLAG_sync,             /* synchronous queue */
        CFQ_CFQQ_FLAG_coop,             /* cfqq is shared */
+       CFQ_CFQQ_FLAG_deep,             /* sync cfqq experienced large depth */
 };
 
 #define CFQ_CFQQ_FNS(name)                                             \
@@ -286,6 +287,7 @@ CFQ_CFQQ_FNS(prio_changed);
 CFQ_CFQQ_FNS(slice_new);
 CFQ_CFQQ_FNS(sync);
 CFQ_CFQQ_FNS(coop);
+CFQ_CFQQ_FNS(deep);
 #undef CFQ_CFQQ_FNS
 
 #define cfq_log_cfqq(cfqd, cfqq, fmt, args...) \
@@ -2350,8 +2352,12 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
 
        enable_idle = old_idle = cfq_cfqq_idle_window(cfqq);
 
+       if (cfqq->queued[0] + cfqq->queued[1] >= 4)
+               cfq_mark_cfqq_deep(cfqq);
+
        if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle ||
-           (sample_valid(cfqq->seek_samples) && CFQQ_SEEKY(cfqq)))
+           (!cfq_cfqq_deep(cfqq) && sample_valid(cfqq->seek_samples)
+            && CFQQ_SEEKY(cfqq)))
                enable_idle = 0;
        else if (sample_valid(cic->ttime_samples)) {
                if (cic->ttime_mean > cfqd->cfq_slice_idle)
@@ -2849,6 +2855,11 @@ static void cfq_idle_slice_timer(unsigned long data)
                 */
                if (!RB_EMPTY_ROOT(&cfqq->sort_list))
                        goto out_kick;
+
+               /*
+                * Queue depth flag is reset only when the idle didn't succeed
+                */
+               cfq_clear_cfqq_deep(cfqq);
        }
 expire:
        cfq_slice_expired(cfqd, timed_out);