mm: compaction: add /proc trigger for memory compaction
[platform/adaptation/renesas_rcar/renesas_kernel.git] / mm / compaction.c
index be1ff3f..77854fb 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/compaction.h>
 #include <linux/mm_inline.h>
 #include <linux/backing-dev.h>
+#include <linux/sysctl.h>
 #include "internal.h"
 
 /*
@@ -391,3 +392,64 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
 
        return ret;
 }
+
+/* Compact all zones within a node */
+static int compact_node(int nid)
+{
+       int zoneid;
+       pg_data_t *pgdat;
+       struct zone *zone;
+
+       if (nid < 0 || nid >= nr_node_ids || !node_online(nid))
+               return -EINVAL;
+       pgdat = NODE_DATA(nid);
+
+       /* Flush pending updates to the LRU lists */
+       lru_add_drain_all();
+
+       for (zoneid = 0; zoneid < MAX_NR_ZONES; zoneid++) {
+               struct compact_control cc = {
+                       .nr_freepages = 0,
+                       .nr_migratepages = 0,
+               };
+
+               zone = &pgdat->node_zones[zoneid];
+               if (!populated_zone(zone))
+                       continue;
+
+               cc.zone = zone;
+               INIT_LIST_HEAD(&cc.freepages);
+               INIT_LIST_HEAD(&cc.migratepages);
+
+               compact_zone(zone, &cc);
+
+               VM_BUG_ON(!list_empty(&cc.freepages));
+               VM_BUG_ON(!list_empty(&cc.migratepages));
+       }
+
+       return 0;
+}
+
+/* Compact all nodes in the system */
+static int compact_nodes(void)
+{
+       int nid;
+
+       for_each_online_node(nid)
+               compact_node(nid);
+
+       return COMPACT_COMPLETE;
+}
+
+/* The written value is actually unused, all memory is compacted */
+int sysctl_compact_memory;
+
+/* This is the entry point for compacting all nodes via /proc/sys/vm */
+int sysctl_compaction_handler(struct ctl_table *table, int write,
+                       void __user *buffer, size_t *length, loff_t *ppos)
+{
+       if (write)
+               return compact_nodes();
+
+       return 0;
+}