dm cache: always split discards on cache block boundaries
[cascardo/linux.git] / mm / vmscan.c
index 3f56c8d..32c661d 100644 (file)
@@ -1915,6 +1915,24 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
        file  = get_lru_size(lruvec, LRU_ACTIVE_FILE) +
                get_lru_size(lruvec, LRU_INACTIVE_FILE);
 
+       /*
+        * Prevent the reclaimer from falling into the cache trap: as
+        * cache pages start out inactive, every cache fault will tip
+        * the scan balance towards the file LRU.  And as the file LRU
+        * shrinks, so does the window for rotation from references.
+        * This means we have a runaway feedback loop where a tiny
+        * thrashing file LRU becomes infinitely more attractive than
+        * anon pages.  Try to detect this based on file LRU size.
+        */
+       if (global_reclaim(sc)) {
+               unsigned long free = zone_page_state(zone, NR_FREE_PAGES);
+
+               if (unlikely(file + free <= high_wmark_pages(zone))) {
+                       scan_balance = SCAN_ANON;
+                       goto out;
+               }
+       }
+
        /*
         * There is enough inactive page cache, do not reclaim
         * anything from the anonymous working set right now.