]> Pileus Git - ~andy/linux/blobdiff - mm/compaction.c
LSM: remove the COMMON_AUDIT_DATA_INIT type expansion
[~andy/linux] / mm / compaction.c
index d9ebebe1a2aaaea69074fe3615faeddd41a4feb7..74a8c825ff289a12079701dfc42be4e1787b8d8f 100644 (file)
@@ -35,7 +35,7 @@ struct compact_control {
        unsigned long migrate_pfn;      /* isolate_migratepages search base */
        bool sync;                      /* Synchronous migration */
 
-       unsigned int order;             /* order a direct compactor needs */
+       int order;                      /* order a direct compactor needs */
        int migratetype;                /* MOVABLE, RECLAIMABLE etc */
        struct zone *zone;
 };
@@ -675,49 +675,71 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist,
 
 
 /* Compact all zones within a node */
-static int compact_node(int nid)
+static int __compact_pgdat(pg_data_t *pgdat, struct compact_control *cc)
 {
        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,
-                       .order = -1,
-                       .sync = true,
-               };
 
                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);
+               cc->nr_freepages = 0;
+               cc->nr_migratepages = 0;
+               cc->zone = zone;
+               INIT_LIST_HEAD(&cc->freepages);
+               INIT_LIST_HEAD(&cc->migratepages);
+
+               if (cc->order == -1 || !compaction_deferred(zone, cc->order))
+                       compact_zone(zone, cc);
+
+               if (cc->order > 0) {
+                       int ok = zone_watermark_ok(zone, cc->order,
+                                               low_wmark_pages(zone), 0, 0);
+                       if (ok && cc->order > zone->compact_order_failed)
+                               zone->compact_order_failed = cc->order + 1;
+                       /* Currently async compaction is never deferred. */
+                       else if (!ok && cc->sync)
+                               defer_compaction(zone, cc->order);
+               }
 
-               VM_BUG_ON(!list_empty(&cc.freepages));
-               VM_BUG_ON(!list_empty(&cc.migratepages));
+               VM_BUG_ON(!list_empty(&cc->freepages));
+               VM_BUG_ON(!list_empty(&cc->migratepages));
        }
 
        return 0;
 }
 
+int compact_pgdat(pg_data_t *pgdat, int order)
+{
+       struct compact_control cc = {
+               .order = order,
+               .sync = false,
+       };
+
+       return __compact_pgdat(pgdat, &cc);
+}
+
+static int compact_node(int nid)
+{
+       struct compact_control cc = {
+               .order = -1,
+               .sync = true,
+       };
+
+       return __compact_pgdat(NODE_DATA(nid), &cc);
+}
+
 /* Compact all nodes in the system */
 static int compact_nodes(void)
 {
        int nid;
 
+       /* Flush pending updates to the LRU lists */
+       lru_add_drain_all();
+
        for_each_online_node(nid)
                compact_node(nid);
 
@@ -750,7 +772,14 @@ ssize_t sysfs_compact_node(struct device *dev,
                        struct device_attribute *attr,
                        const char *buf, size_t count)
 {
-       compact_node(dev->id);
+       int nid = dev->id;
+
+       if (nid >= 0 && nid < nr_node_ids && node_online(nid)) {
+               /* Flush pending updates to the LRU lists */
+               lru_add_drain_all();
+
+               compact_node(nid);
+       }
 
        return count;
 }