mm: compaction: optimize proactive compaction deferrals
[linux-2.6-microblaze.git] / mm / compaction.c
index 61fb64f..4ee0d40 100644 (file)
@@ -2885,7 +2885,8 @@ static int kcompactd(void *p)
 {
        pg_data_t *pgdat = (pg_data_t *)p;
        struct task_struct *tsk = current;
-       unsigned int proactive_defer = 0;
+       long default_timeout = msecs_to_jiffies(HPAGE_FRAG_CHECK_INTERVAL_MSEC);
+       long timeout = default_timeout;
 
        const struct cpumask *cpumask = cpumask_of_node(pgdat->node_id);
 
@@ -2902,23 +2903,30 @@ static int kcompactd(void *p)
 
                trace_mm_compaction_kcompactd_sleep(pgdat->node_id);
                if (wait_event_freezable_timeout(pgdat->kcompactd_wait,
-                       kcompactd_work_requested(pgdat),
-                       msecs_to_jiffies(HPAGE_FRAG_CHECK_INTERVAL_MSEC))) {
+                       kcompactd_work_requested(pgdat), timeout)) {
 
                        psi_memstall_enter(&pflags);
                        kcompactd_do_work(pgdat);
                        psi_memstall_leave(&pflags);
+                       /*
+                        * Reset the timeout value. The defer timeout from
+                        * proactive compaction is lost here but that is fine
+                        * as the condition of the zone changing substantionally
+                        * then carrying on with the previous defer interval is
+                        * not useful.
+                        */
+                       timeout = default_timeout;
                        continue;
                }
 
-               /* kcompactd wait timeout */
+               /*
+                * Start the proactive work with default timeout. Based
+                * on the fragmentation score, this timeout is updated.
+                */
+               timeout = default_timeout;
                if (should_proactive_compact_node(pgdat)) {
                        unsigned int prev_score, score;
 
-                       if (proactive_defer) {
-                               proactive_defer--;
-                               continue;
-                       }
                        prev_score = fragmentation_score_node(pgdat);
                        proactive_compact_node(pgdat);
                        score = fragmentation_score_node(pgdat);
@@ -2926,8 +2934,9 @@ static int kcompactd(void *p)
                         * Defer proactive compaction if the fragmentation
                         * score did not go down i.e. no progress made.
                         */
-                       proactive_defer = score < prev_score ?
-                                       0 : 1 << COMPACT_MAX_DEFER_SHIFT;
+                       if (unlikely(score >= prev_score))
+                               timeout =
+                                  default_timeout << COMPACT_MAX_DEFER_SHIFT;
                }
        }