]> Pileus Git - ~andy/linux/blobdiff - mm/vmscan.c
Merge tag 'byteswap-for-linus-20121219' of git://git.infradead.org/users/dwmw2/byteswap
[~andy/linux] / mm / vmscan.c
index 157bb116dec883f7a5075b2078f83a7022080820..828530e2794a352055eecdcaaff1db79aaafdd3c 100644 (file)
@@ -1177,7 +1177,11 @@ int isolate_lru_page(struct page *page)
 }
 
 /*
- * Are there way too many processes in the direct reclaim path already?
+ * A direct reclaimer may isolate SWAP_CLUSTER_MAX pages from the LRU list and
+ * then get resheduled. When there are massive number of tasks doing page
+ * allocation, such sleeping direct reclaimers may keep piling up on each CPU,
+ * the LRU list will go small and be scanned faster than necessary, leading to
+ * unnecessary swapping, thrashing and OOM.
  */
 static int too_many_isolated(struct zone *zone, int file,
                struct scan_control *sc)
@@ -1198,6 +1202,14 @@ static int too_many_isolated(struct zone *zone, int file,
                isolated = zone_page_state(zone, NR_ISOLATED_ANON);
        }
 
+       /*
+        * GFP_NOIO/GFP_NOFS callers are allowed to isolate more pages, so they
+        * won't get blocked by normal direct-reclaimers, forming a circular
+        * deadlock.
+        */
+       if ((sc->gfp_mask & GFP_IOFS) == GFP_IOFS)
+               inactive >>= 3;
+
        return isolated > inactive;
 }
 
@@ -3131,7 +3143,7 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
        int nid;
 
        if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN) {
-               for_each_node_state(nid, N_HIGH_MEMORY) {
+               for_each_node_state(nid, N_MEMORY) {
                        pg_data_t *pgdat = NODE_DATA(nid);
                        const struct cpumask *mask;
 
@@ -3187,7 +3199,7 @@ static int __init kswapd_init(void)
        int nid;
 
        swap_setup();
-       for_each_node_state(nid, N_HIGH_MEMORY)
+       for_each_node_state(nid, N_MEMORY)
                kswapd_run(nid);
        hotcpu_notifier(cpu_callback, 0);
        return 0;