|
@@ -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))
|