diff -pruN linux-5.10.0-60.139.0.166.oe2203.x86_64-old/include/linux/mmzone.h linux-5.10.0-60.139.0.166.oe2203.x86_64/include/linux/mmzone.h
--- linux-5.10.0-60.139.0.166.oe2203.x86_64-old/include/linux/mmzone.h	2024-05-29 08:00:00.000000000 +0800
+++ linux-5.10.0-60.139.0.166.oe2203.x86_64/include/linux/mmzone.h	2024-11-04 10:37:10.922388662 +0800
@@ -451,6 +451,14 @@ struct zone {
 	 */
 	long lowmem_reserve[MAX_NR_ZONES];
 
+ 	/*
+	 * This atomic counter is set when there is pagecache limit
+	 * reclaim going on on this particular zone. Other potential
+	 * reclaiers should back off to prevent from heavy lru_lock
+	 * bouncing.
+	 */
+	atomic_t		pagecache_reclaim;
+
 #ifdef CONFIG_NEED_MULTIPLE_NODES
 	int node;
 #endif
diff -pruN linux-5.10.0-60.139.0.166.oe2203.x86_64-old/include/linux/pagemap.h linux-5.10.0-60.139.0.166.oe2203.x86_64/include/linux/pagemap.h
--- linux-5.10.0-60.139.0.166.oe2203.x86_64-old/include/linux/pagemap.h	2024-05-29 08:00:00.000000000 +0800
+++ linux-5.10.0-60.139.0.166.oe2203.x86_64/include/linux/pagemap.h	2024-11-04 10:41:12.513174946 +0800
@@ -756,6 +756,8 @@ static inline int fault_in_pages_readabl
 	return 0;
 }
 
+int add_to_page_cache(struct page *page, struct address_space *mapping,
+				pgoff_t index, gfp_t gfp_mask);
 int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
 				pgoff_t index, gfp_t gfp_mask);
 int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
@@ -768,22 +770,6 @@ void delete_from_page_cache_batch(struct
 loff_t mapping_seek_hole_data(struct address_space *, loff_t start, loff_t end,
 		int whence);
 
-/*
- * Like add_to_page_cache_locked, but used to add newly allocated pages:
- * the page is new, so we can just run __SetPageLocked() against it.
- */
-static inline int add_to_page_cache(struct page *page,
-		struct address_space *mapping, pgoff_t offset, gfp_t gfp_mask)
-{
-	int error;
-
-	__SetPageLocked(page);
-	error = add_to_page_cache_locked(page, mapping, offset, gfp_mask);
-	if (unlikely(error))
-		__ClearPageLocked(page);
-	return error;
-}
-
 /**
  * struct readahead_control - Describes a readahead request.
  *
diff -pruN linux-5.10.0-60.139.0.166.oe2203.x86_64-old/include/linux/swap.h linux-5.10.0-60.139.0.166.oe2203.x86_64/include/linux/swap.h
--- linux-5.10.0-60.139.0.166.oe2203.x86_64-old/include/linux/swap.h	2024-05-29 08:00:00.000000000 +0800
+++ linux-5.10.0-60.139.0.166.oe2203.x86_64/include/linux/swap.h	2024-11-04 10:42:06.524468554 +0800
@@ -380,6 +380,14 @@ extern unsigned long mem_cgroup_shrink_n
 						unsigned long *nr_scanned);
 extern unsigned long shrink_all_memory(unsigned long nr_pages);
 extern int vm_swappiness;
+#define ADDITIONAL_RECLAIM_RATIO 2
+extern unsigned long pagecache_over_limit(void);
+extern void shrink_page_cache(gfp_t mask, struct page *page);
+extern unsigned long vm_pagecache_limit_pages;
+extern unsigned long vm_pagecache_limit_reclaim_pages;
+extern int vm_pagecache_limit_ratio;
+extern int vm_pagecache_limit_reclaim_ratio;
+extern unsigned int vm_pagecache_ignore_dirty;
 extern int remove_mapping(struct address_space *mapping, struct page *page);
 
 extern unsigned long reclaim_pages(struct list_head *page_list);
diff -pruN linux-5.10.0-60.139.0.166.oe2203.x86_64-old/kernel/sysctl.c linux-5.10.0-60.139.0.166.oe2203.x86_64/kernel/sysctl.c
--- linux-5.10.0-60.139.0.166.oe2203.x86_64-old/kernel/sysctl.c	2024-05-29 08:00:00.000000000 +0800
+++ linux-5.10.0-60.139.0.166.oe2203.x86_64/kernel/sysctl.c	2024-11-04 10:46:13.310379262 +0800
@@ -682,6 +682,48 @@ static int do_proc_dointvec(struct ctl_t
 			buffer, lenp, ppos, conv, data);
 }
 
+int setup_pagecache_limit(void)
+{
+	/* reclaim $ADDITIONAL_RECLAIM_PAGES more than limit. */
+	vm_pagecache_limit_reclaim_ratio = vm_pagecache_limit_ratio + ADDITIONAL_RECLAIM_RATIO;
+
+	if (vm_pagecache_limit_reclaim_ratio > 100)
+		vm_pagecache_limit_reclaim_ratio = 100;
+	if (vm_pagecache_limit_ratio == 0)
+		vm_pagecache_limit_reclaim_ratio = 0;
+
+	vm_pagecache_limit_pages = vm_pagecache_limit_ratio * totalram_pages() / 100;
+	vm_pagecache_limit_reclaim_pages = vm_pagecache_limit_reclaim_ratio * totalram_pages() / 100;
+	return 0;
+}
+
+static int pc_limit_proc_dointvec(struct ctl_table *table, int write,
+		     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	int ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+	if (write && !ret)
+		ret = setup_pagecache_limit();
+	return ret;
+}
+
+int pc_reclaim_limit_proc_dointvec(struct ctl_table *table, int write,
+		     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	if (write && vm_pagecache_limit_ratio == 0)
+		return -EINVAL;
+
+	int pre_reclaim_ratio = vm_pagecache_limit_reclaim_ratio;
+	int ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+	if (write && !ret) {
+		if (vm_pagecache_limit_reclaim_ratio - vm_pagecache_limit_ratio < ADDITIONAL_RECLAIM_RATIO) {
+			vm_pagecache_limit_reclaim_ratio = pre_reclaim_ratio;
+			return -EINVAL;
+		}
+		vm_pagecache_limit_reclaim_pages = vm_pagecache_limit_reclaim_ratio * totalram_pages() / 100;
+	}
+	return ret;
+}
+
 static int do_proc_douintvec_w(unsigned int *tbl_data,
 			       struct ctl_table *table,
 			       void *buffer,
@@ -2722,6 +2764,12 @@ static struct ctl_table kern_table[] = {
 	{ }
 };
 
+int pc_limit_proc_dointvec(struct ctl_table *table, int write,
+		     void __user *buffer, size_t *lenp, loff_t *ppos);
+
+int pc_reclaim_limit_proc_dointvec(struct ctl_table *table, int write,
+		     void __user *buffer, size_t *lenp, loff_t *ppos);
+
 static struct ctl_table vm_table[] = {
 	{
 		.procname	= "overcommit_memory",
@@ -2854,6 +2902,31 @@ static struct ctl_table vm_table[] = {
 		.extra1		= SYSCTL_ZERO,
 		.extra2		= &two_hundred,
 	},
+	{
+		.procname	= "pagecache_limit_ratio",
+		.data		= &vm_pagecache_limit_ratio,
+		.maxlen		= sizeof(vm_pagecache_limit_ratio),
+		.mode		= 0644,
+		.proc_handler	= &pc_limit_proc_dointvec,
+		.extra1		= SYSCTL_ZERO,
+		.extra2		= &one_hundred,
+	},
+	{
+		.procname	= "pagecache_limit_reclaim_ratio",
+		.data		= &vm_pagecache_limit_reclaim_ratio,
+		.maxlen		= sizeof(vm_pagecache_limit_reclaim_ratio),
+		.mode		= 0644,
+		.proc_handler	= &pc_reclaim_limit_proc_dointvec,
+		.extra1		= SYSCTL_ZERO,
+		.extra2		= &one_hundred,
+	},
+	{
+		.procname	= "pagecache_limit_ignore_dirty",
+		.data		= &vm_pagecache_ignore_dirty,
+		.maxlen		= sizeof(vm_pagecache_ignore_dirty),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
 #ifdef CONFIG_NUMA
 	{
 		.procname	= "numa_stat",
diff -pruN linux-5.10.0-60.139.0.166.oe2203.x86_64-old/mm/filemap.c linux-5.10.0-60.139.0.166.oe2203.x86_64/mm/filemap.c
--- linux-5.10.0-60.139.0.166.oe2203.x86_64-old/mm/filemap.c	2024-05-29 08:00:00.000000000 +0800
+++ linux-5.10.0-60.139.0.166.oe2203.x86_64/mm/filemap.c	2024-11-04 10:48:52.794199015 +0800
@@ -917,12 +917,35 @@ int add_to_page_cache_locked(struct page
 }
 EXPORT_SYMBOL(add_to_page_cache_locked);
 
+/*
+ * Like add_to_page_cache_locked, but used to add newly allocated pages:
+ * the page is new, so we can just run __set_page_locked() against it.
+ */
+int add_to_page_cache(struct page *page,
+		struct address_space *mapping, pgoff_t offset, gfp_t gfp_mask)
+{
+	int error;
+
+	if (unlikely(vm_pagecache_limit_pages) && pagecache_over_limit() > 0)
+		shrink_page_cache(gfp_mask, page);
+
+	__SetPageLocked(page);
+	error = add_to_page_cache_locked(page, mapping, offset, gfp_mask);
+	if (unlikely(error))
+		__ClearPageLocked(page);
+	return error;
+}
+EXPORT_SYMBOL(add_to_page_cache);
+
 int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
 				pgoff_t offset, gfp_t gfp_mask)
 {
 	void *shadow = NULL;
 	int ret;
 
+	if (unlikely(vm_pagecache_limit_pages) && pagecache_over_limit() > 0)
+		shrink_page_cache(gfp_mask, page);
+
 	__SetPageLocked(page);
 	ret = __add_to_page_cache_locked(page, mapping, offset,
 					 gfp_mask, &shadow);
diff -pruN linux-5.10.0-60.139.0.166.oe2203.x86_64-old/mm/page_alloc.c linux-5.10.0-60.139.0.166.oe2203.x86_64/mm/page_alloc.c
--- linux-5.10.0-60.139.0.166.oe2203.x86_64-old/mm/page_alloc.c	2024-05-29 08:00:00.000000000 +0800
+++ linux-5.10.0-60.139.0.166.oe2203.x86_64/mm/page_alloc.c	2024-11-04 10:51:17.009653088 +0800
@@ -9099,6 +9099,49 @@ void zone_pcp_reset(struct zone *zone)
 	local_irq_restore(flags);
 }
 
+/* Returns a number that's positive if the pagecache is above
+ * the set limit*/
+unsigned long pagecache_over_limit()
+{
+	unsigned long should_reclaim_pages = 0;
+	unsigned long overlimit_pages = 0;
+	unsigned long delta_pages = 0;
+	/* We only want to limit unmapped and non-shmem page cache pages;
+	 * normally all shmem pages are mapped as well*/
+	unsigned long pgcache_pages = global_node_page_state(NR_FILE_PAGES)
+				    - max_t(unsigned long,
+					    global_node_page_state(NR_FILE_MAPPED),
+					    global_node_page_state(NR_SHMEM));
+	/* We certainly can't free more than what's on the LRU lists
+	 * minus the dirty ones*/
+	unsigned long pgcache_lru_pages = global_node_page_state(NR_ACTIVE_FILE)
+				        + global_node_page_state(NR_INACTIVE_FILE);
+
+	if (vm_pagecache_ignore_dirty != 0)
+		pgcache_lru_pages -= global_node_page_state(NR_FILE_DIRTY)
+				     /vm_pagecache_ignore_dirty;
+	/* Paranoia */
+	if (unlikely(pgcache_lru_pages > LONG_MAX))
+		return 0;
+
+	/* Limit it to 94% of LRU (not all there might be unmapped) */
+	pgcache_lru_pages -= pgcache_lru_pages/16;
+	pgcache_pages = min_t(unsigned long, pgcache_pages, pgcache_lru_pages);
+
+	/*
+	*delta_pages: we should reclaim at least 2% more pages than overlimit_page, values get from
+	*		/proc/vm/pagecache_limit_reclaim_pages
+	*should_reclaim_pages: the real pages we will reclaim, but it should less than pgcache_pages;
+	*/
+	if (pgcache_pages > vm_pagecache_limit_pages) {
+		overlimit_pages = pgcache_pages - vm_pagecache_limit_pages;
+		delta_pages = vm_pagecache_limit_reclaim_pages - vm_pagecache_limit_pages;
+		should_reclaim_pages = min_t(unsigned long, delta_pages, vm_pagecache_limit_pages) +  overlimit_pages;
+		return should_reclaim_pages;
+	}
+	return 0;
+}
+
 #ifdef CONFIG_MEMORY_HOTREMOVE
 /*
  * All pages in the range must be in a single zone, must not contain holes,
diff -pruN linux-5.10.0-60.139.0.166.oe2203.x86_64-old/mm/shmem.c linux-5.10.0-60.139.0.166.oe2203.x86_64/mm/shmem.c
--- linux-5.10.0-60.139.0.166.oe2203.x86_64-old/mm/shmem.c	2024-05-29 08:00:00.000000000 +0800
+++ linux-5.10.0-60.139.0.166.oe2203.x86_64/mm/shmem.c	2024-11-04 10:55:23.104547247 +0800
@@ -1310,6 +1310,17 @@ int shmem_unuse(unsigned int type, bool
 	if (list_empty(&shmem_swaplist))
 		return 0;
 
+	/*
+	 * try to shrink the page cache proactively even though
+	 * we might already have the page in so the shrinking is
+	 * not necessary but this is much easier than dropping
+	 * the lock in shmem_unuse_inode before add_to_page_cache_lru.
+	 * GFP_NOWAIT makes sure that we do not shrink when adding
+	 * to page cache
+	 */
+	if (unlikely(vm_pagecache_limit_pages) && pagecache_over_limit() > 0)
+		shrink_page_cache(GFP_KERNEL, NULL);
+
 	mutex_lock(&shmem_swaplist_mutex);
 	list_for_each_entry_safe(info, next, &shmem_swaplist, swaplist) {
 		if (!info->swapped) {
@@ -1340,6 +1351,10 @@ int shmem_unuse(unsigned int type, bool
 	}
 	mutex_unlock(&shmem_swaplist_mutex);
 
+	if (!error && (unlikely(vm_pagecache_limit_pages) && pagecache_over_limit() > 0)) {
+		shrink_page_cache(GFP_KERNEL, NULL);		
+	}
+
 	return error;
 }
 
diff -pruN linux-5.10.0-60.139.0.166.oe2203.x86_64-old/mm/vmscan.c linux-5.10.0-60.139.0.166.oe2203.x86_64/mm/vmscan.c
--- linux-5.10.0-60.139.0.166.oe2203.x86_64-old/mm/vmscan.c	2024-05-29 08:00:00.000000000 +0800
+++ linux-5.10.0-60.139.0.166.oe2203.x86_64/mm/vmscan.c	2024-11-04 11:06:08.478011368 +0800
@@ -176,6 +176,11 @@ struct scan_control {
  * From 0 .. 200.  Higher means more swappy.
  */
 int vm_swappiness = 60;
+unsigned long vm_pagecache_limit_pages __read_mostly = 0;
+unsigned long vm_pagecache_limit_reclaim_pages = 0;
+int vm_pagecache_limit_ratio __read_mostly = 0;
+int vm_pagecache_limit_reclaim_ratio __read_mostly = 0;
+unsigned int vm_pagecache_ignore_dirty __read_mostly = 1;
 
 static void set_task_reclaim_state(struct task_struct *task,
 				   struct reclaim_state *rs)
@@ -3811,6 +3816,8 @@ static bool kswapd_shrink_node(pg_data_t
 	return sc->nr_scanned >= sc->nr_to_reclaim;
 }
 
+static void __shrink_page_cache(gfp_t mask);
+
 /*
  * For kswapd, balance_pgdat() will reclaim pages across a node from zones
  * that are eligible for use by the caller until at least one zone is
@@ -3846,6 +3853,10 @@ static int balance_pgdat(pg_data_t *pgda
 
 	count_vm_event(PAGEOUTRUN);
 
+	/* this reclaims from all zones so don't count to sc.nr_reclaimed */
+	if (unlikely(vm_pagecache_limit_pages) && pagecache_over_limit() > 0)
+		__shrink_page_cache(GFP_KERNEL);
+
 	/*
 	 * Account for the reclaim boost. Note that the zone boost is left in
 	 * place so that parallel allocations that are near the watermark will
@@ -4104,6 +4115,12 @@ static void kswapd_try_to_sleep(pg_data_
 		prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE);
 	}
 
+	/* We do not need to loop_again if we have not achieved our
+	 * pagecache target (i.e. && pagecache_over_limit(0) > 0) because
+	 * the limit will be checked next time a page is added to the page
+	 * cache. This might cause a short stall but we should rather not
+	 * keep kswapd awake.
+	 */
 	/*
 	 * After a short sleep, check if it was a premature sleep. If not, then
 	 * go fully to sleep until explicitly woken up.
@@ -4278,6 +4295,27 @@ void wakeup_kswapd(struct zone *zone, gf
 	wake_up_interruptible(&pgdat->kswapd_wait);
 }
 
+/*
+ *  * The reclaimable count would be mostly accurate.
+ *   * The less reclaimable pages may be
+ *    * - mlocked pages, which will be moved to unevictable list when encountered
+ *     * - mapped pages, which may require several travels to be reclaimed
+ *      * - dirty pages, which is not "instantly" reclaimable
+ *      *	*/
+
+static unsigned long global_reclaimable_pages(void)
+{
+        int nr;
+
+        nr = global_node_page_state(NR_ACTIVE_FILE) +
+             global_node_page_state(NR_INACTIVE_FILE);
+
+        if (get_nr_swap_pages() > 0)
+                nr += global_node_page_state(NR_ACTIVE_ANON) +
+                      global_node_page_state(NR_INACTIVE_ANON);
+        return nr;
+}
+
 #ifdef CONFIG_HIBERNATION
 /*
  * Try to free `nr_to_reclaim' of memory, system-wide, and return the number of
@@ -4322,6 +4360,286 @@ unsigned long shrink_all_memory(unsigned
 #endif /* CONFIG_HIBERNATION */
 
 /*
+ * Returns non-zero if the lock has been acquired, false if somebody
+ * else is holding the lock.
+ */
+static int pagecache_reclaim_lock_zone(struct zone *zone)
+{
+	return atomic_add_unless(&zone->pagecache_reclaim, 1, 1);
+}
+
+static void pagecache_reclaim_unlock_zone(struct zone *zone)
+{
+	BUG_ON(atomic_dec_return(&zone->pagecache_reclaim));
+}
+
+/*
+ * Potential page cache reclaimers who are not able to take
+ * reclaim lock on any zone are sleeping on this waitqueue.
+ * So this is basically a congestion wait queue for them.
+ */
+DECLARE_WAIT_QUEUE_HEAD(pagecache_reclaim_wq);
+
+/*
+ * Similar to shrink_zone but it has a different consumer - pagecache limit
+ * so we cannot reuse the original function - and we do not want to clobber
+ * that code path so we have to live with this code duplication.
+ *
+ * In short this simply scans through the given lru for all cgroups for the
+ * give zone.
+ *
+ * returns true if we managed to cumulatively reclaim (via nr_reclaimed)
+ * the given nr_to_reclaim pages, false otherwise. The caller knows that
+ * it doesn't have to touch other zones if the target was hit already.
+ *
+ * DO NOT USE OUTSIDE of shrink_all_zones unless you have a really really
+ * really good reason.
+ */
+static bool shrink_zone_per_memcg(struct zone *zone, enum lru_list lru,
+		unsigned long nr_to_scan, unsigned long nr_to_reclaim,
+		unsigned long *nr_reclaimed, struct scan_control *sc)
+{
+	struct mem_cgroup *root = sc->target_mem_cgroup;
+	struct mem_cgroup *memcg;
+	struct mem_cgroup_reclaim_cookie reclaim = {
+		.pgdat = zone->zone_pgdat,
+	};
+
+	memcg = mem_cgroup_iter(root, NULL, &reclaim);
+	do {
+		struct lruvec *lruvec;
+
+		lruvec = mem_cgroup_lruvec(memcg, zone->zone_pgdat);
+		*nr_reclaimed += shrink_list(lru, nr_to_scan, lruvec, sc);
+		if (*nr_reclaimed >= nr_to_reclaim) {
+			mem_cgroup_iter_break(root, memcg);
+			return true;
+		}
+		memcg = mem_cgroup_iter(root, memcg, &reclaim);
+	} while (memcg);
+
+	return false;
+}
+
+/*
+ * Tries to reclaim 'nr_pages' pages from LRU lists system-wide, for given
+ * pass.
+ *
+ * For pass > 3 we also try to shrink the LRU lists that contain a few pages
+ *
+ * Returns the number of scanned zones.
+ */
+static int shrink_all_zones(unsigned long nr_pages, int pass,
+		struct scan_control *sc)
+{
+	struct zone *zone;
+	unsigned long nr_reclaimed = 0;
+	unsigned int nr_locked_zones = 0;
+	DEFINE_WAIT(wait);
+
+	prepare_to_wait(&pagecache_reclaim_wq, &wait, TASK_INTERRUPTIBLE);
+
+	for_each_populated_zone(zone) {
+		enum lru_list lru;
+
+		/*
+		 * Back off if somebody is already reclaiming this zone
+		 * for the pagecache reclaim.
+		 */
+		if (!pagecache_reclaim_lock_zone(zone))
+			continue;
+
+
+		/*
+		 * This reclaimer might scan a zone so it will never
+		 * sleep on pagecache_reclaim_wq
+		 */
+		finish_wait(&pagecache_reclaim_wq, &wait);
+		nr_locked_zones++;
+
+		for_each_evictable_lru(lru) {
+			enum zone_stat_item ls = NR_ZONE_LRU_BASE + lru;
+			unsigned long lru_pages = zone_page_state(zone, ls);
+
+			/* For pass = 0, we don't shrink the active list */
+			if (pass == 0 && (lru == LRU_ACTIVE_ANON ||
+						lru == LRU_ACTIVE_FILE))
+				continue;
+
+			/* Original code relied on nr_saved_scan which is no
+			 * longer present so we are just considering LRU pages.
+			 * This means that the zone has to have quite large
+			 * LRU list for default priority and minimum nr_pages
+			 * size (8*SWAP_CLUSTER_MAX). In the end we will tend
+			 * to reclaim more from large zones wrt. small.
+			 * This should be OK because shrink_page_cache is called
+			 * when we are getting to short memory condition so
+			 * LRUs tend to be large.
+			 */
+			if (((lru_pages >> sc->priority) + 1) >= nr_pages || pass >= 3) {
+				unsigned long nr_to_scan;
+
+				nr_to_scan = min(nr_pages, lru_pages);
+
+				/*
+				 * A bit of a hack but the code has always been
+				 * updating sc->nr_reclaimed once per shrink_all_zones
+				 * rather than accumulating it for all calls to shrink
+				 * lru. This costs us an additional argument to
+				 * shrink_zone_per_memcg but well...
+				 *
+				 * Let's stick with this for bug-to-bug compatibility
+				 */
+				while (nr_to_scan > 0) {
+					/* shrink_list takes lru_lock with IRQ off so we
+					 * should be careful about really huge nr_to_scan
+					 */
+					unsigned long batch = min_t(unsigned long, nr_to_scan, SWAP_CLUSTER_MAX);
+
+					if (shrink_zone_per_memcg(zone, lru,
+						batch, nr_pages, &nr_reclaimed, sc)) {
+						pagecache_reclaim_unlock_zone(zone);
+						goto out_wakeup;
+					}
+					nr_to_scan -= batch;
+				}
+			}
+		}
+		pagecache_reclaim_unlock_zone(zone);
+	}
+
+	/*
+	 * We have to go to sleep because all the zones are already reclaimed.
+	 * One of the reclaimer will wake us up or __shrink_page_cache will
+	 * do it if there is nothing to be done.
+	 */
+	if (!nr_locked_zones) {
+		schedule();
+		finish_wait(&pagecache_reclaim_wq, &wait);
+		goto out;
+	}
+
+out_wakeup:
+	wake_up_interruptible(&pagecache_reclaim_wq);
+	sc->nr_reclaimed += nr_reclaimed;
+out:
+	return nr_locked_zones;
+}
+
+/*
+ * Function to shrink the page cache
+ *
+ * This function calculates the number of pages (nr_pages) the page
+ * cache is over its limit and shrinks the page cache accordingly.
+ *
+ * The maximum number of pages, the page cache shrinks in one call of
+ * this function is limited to SWAP_CLUSTER_MAX pages. Therefore it may
+ * require a number of calls to actually reach the vm_pagecache_limit_kb.
+ *
+ * This function is similar to shrink_all_memory, except that it may never
+ * swap out mapped pages and only does four passes.
+ */
+static void __shrink_page_cache(gfp_t mask)
+{
+	unsigned long ret = 0;
+	int pass = 0;
+	struct reclaim_state reclaim_state;
+	struct scan_control sc = {
+		.gfp_mask = mask,
+		.may_swap = 0,
+		.may_unmap = 0,
+		.may_writepage = 0,
+		.target_mem_cgroup = NULL,
+		.reclaim_idx = MAX_NR_ZONES,
+	};
+	struct reclaim_state *old_rs = current->reclaim_state;
+	long nr_pages;
+
+	/* We might sleep during direct reclaim so make atomic context
+	 * is certainly a bug.
+	 */
+	BUG_ON(!(mask & __GFP_RECLAIM));
+
+retry:
+	/* How many pages are we over the limit?*/
+	nr_pages = pagecache_over_limit();
+
+	/*
+	 * Return early if there's no work to do.
+	 * Wake up reclaimers that couldn't scan any zone due to congestion.
+	 * There is apparently nothing to do so they do not have to sleep.
+	 * This makes sure that no sleeping reclaimer will stay behind.
+	 * Allow breaching the limit if the task is on the way out.
+	 */
+	if (nr_pages <= 0 || fatal_signal_pending(current)) {
+		wake_up_interruptible(&pagecache_reclaim_wq);
+		goto out;
+	}
+
+	/* But do a few at least */
+	nr_pages = max_t(unsigned long, nr_pages, 8*SWAP_CLUSTER_MAX);
+
+	current->reclaim_state = &reclaim_state;
+
+	/*
+	 * Shrink the LRU in 4 passes:
+	 * 0 = Reclaim from inactive_list only (fast)
+	 * 1 = Reclaim from active list but don't reclaim mapped and dirtied (not that fast)
+	 * 2 = Reclaim from active list but don't reclaim mapped (2nd pass)
+	 * it may reclaim dirtied if  vm_pagecache_ignore_dirty = 0
+	 * 3 = same as pass 2, but it will reclaim some few pages , detail in shrink_all_zones
+	 */
+	for (; pass <= 3; pass++) {
+		for (sc.priority = DEF_PRIORITY; sc.priority >= 0; sc.priority--) {
+			unsigned long nr_to_scan = nr_pages - ret;
+			int nid;
+
+			sc.nr_scanned = 0;
+
+			/*
+			 * No zone reclaimed because of too many reclaimers. Retry whether
+			 * there is still something to do
+			 */
+			if (!shrink_all_zones(nr_to_scan, pass, &sc))
+				goto retry;
+
+			ret += sc.nr_reclaimed;
+			if (ret >= nr_pages)
+				goto out;
+
+			reclaim_state.reclaimed_slab = 0;
+			for_each_online_node(nid) {
+			  struct mem_cgroup *memcg = mem_cgroup_iter(NULL, NULL, NULL);
+
+			  do {
+			    shrink_slab(mask, nid, memcg, sc.priority);
+			  } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL)) != NULL);
+			}
+			ret += reclaim_state.reclaimed_slab;
+
+			if (ret >= nr_pages)
+				goto out;
+
+		}
+		if (pass == 1) {
+			if (vm_pagecache_ignore_dirty == 1 ||
+			    (mask & (__GFP_IO | __GFP_FS)) != (__GFP_IO | __GFP_FS) )
+				break;
+			else
+				sc.may_writepage = 1;
+		}
+	}
+
+out:
+	current->reclaim_state = old_rs;
+}
+
+void shrink_page_cache(gfp_t mask, struct page *page)
+{
+	__shrink_page_cache(mask);
+}
+
+/*
  * This kswapd start function will be called by init and node-hot-add.
  * On node-hot-add, kswapd will moved to proper cpus if cpus are hot-added.
  */
