vmscan: properly account for the number of page cache pages zone_reclaim() can reclaim
[sfrench/cifs-2.6.git] / mm / vmscan.c
index 057e44b97aa1d2d6fdbee6de0a2a6008a51cf894..79a98d98ed33c56a96c43502379bbd263692bfea 100644 (file)
@@ -2356,6 +2356,48 @@ int sysctl_min_unmapped_ratio = 1;
  */
 int sysctl_min_slab_ratio = 5;
 
+static inline unsigned long zone_unmapped_file_pages(struct zone *zone)
+{
+       unsigned long file_mapped = zone_page_state(zone, NR_FILE_MAPPED);
+       unsigned long file_lru = zone_page_state(zone, NR_INACTIVE_FILE) +
+               zone_page_state(zone, NR_ACTIVE_FILE);
+
+       /*
+        * It's possible for there to be more file mapped pages than
+        * accounted for by the pages on the file LRU lists because
+        * tmpfs pages accounted for as ANON can also be FILE_MAPPED
+        */
+       return (file_lru > file_mapped) ? (file_lru - file_mapped) : 0;
+}
+
+/* Work out how many page cache pages we can reclaim in this reclaim_mode */
+static long zone_pagecache_reclaimable(struct zone *zone)
+{
+       long nr_pagecache_reclaimable;
+       long delta = 0;
+
+       /*
+        * If RECLAIM_SWAP is set, then all file pages are considered
+        * potentially reclaimable. Otherwise, we have to worry about
+        * pages like swapcache and zone_unmapped_file_pages() provides
+        * a better estimate
+        */
+       if (zone_reclaim_mode & RECLAIM_SWAP)
+               nr_pagecache_reclaimable = zone_page_state(zone, NR_FILE_PAGES);
+       else
+               nr_pagecache_reclaimable = zone_unmapped_file_pages(zone);
+
+       /* If we can't clean pages, remove dirty pages from consideration */
+       if (!(zone_reclaim_mode & RECLAIM_WRITE))
+               delta += zone_page_state(zone, NR_FILE_DIRTY);
+
+       /* Watch for any possible underflows due to delta */
+       if (unlikely(delta > nr_pagecache_reclaimable))
+               delta = nr_pagecache_reclaimable;
+
+       return nr_pagecache_reclaimable - delta;
+}
+
 /*
  * Try to free up some pages from this zone through reclaim.
  */
@@ -2390,9 +2432,7 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
        reclaim_state.reclaimed_slab = 0;
        p->reclaim_state = &reclaim_state;
 
-       if (zone_page_state(zone, NR_FILE_PAGES) -
-               zone_page_state(zone, NR_FILE_MAPPED) >
-               zone->min_unmapped_pages) {
+       if (zone_pagecache_reclaimable(zone) > zone->min_unmapped_pages) {
                /*
                 * Free memory by calling shrink zone with increasing
                 * priorities until we have enough memory freed.
@@ -2450,10 +2490,8 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
         * if less than a specified percentage of the zone is used by
         * unmapped file backed pages.
         */
-       if (zone_page_state(zone, NR_FILE_PAGES) -
-           zone_page_state(zone, NR_FILE_MAPPED) <= zone->min_unmapped_pages
-           && zone_page_state(zone, NR_SLAB_RECLAIMABLE)
-                       <= zone->min_slab_pages)
+       if (zone_pagecache_reclaimable(zone) <= zone->min_unmapped_pages &&
+           zone_page_state(zone, NR_SLAB_RECLAIMABLE) <= zone->min_slab_pages)
                return 0;
 
        if (zone_is_all_unreclaimable(zone))