提交 e56e8310 编写于 作者: C Chen Wandun 提交者: Zheng Zengkai

mm/page_cache_limit: add support for droping caches for target node

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4HOXK

------------------------------------------

Add a proc interface to drop cache in target node.
Signed-off-by: NChen Wandun <chenwandun@huawei.com>
Reviewed-by: NKefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 9fea105d
......@@ -9,12 +9,17 @@
#include <linux/writeback.h>
#include <linux/sysctl.h>
#include <linux/gfp.h>
#ifdef CONFIG_SHRINK_PAGECACHE
#include <linux/page_cache_limit.h>
#endif
#include "internal.h"
/* A global variable is a bit ugly, but it keeps the code simple */
int sysctl_drop_caches;
static void drop_pagecache_sb(struct super_block *sb, void *unused)
static void drop_pagecache_sb(struct super_block *sb, void *nid)
{
struct inode *inode, *toput_inode = NULL;
......@@ -35,7 +40,12 @@ static void drop_pagecache_sb(struct super_block *sb, void *unused)
spin_unlock(&inode->i_lock);
spin_unlock(&sb->s_inode_list_lock);
invalidate_mapping_pages(inode->i_mapping, 0, -1);
if (!nid)
invalidate_mapping_pages(inode->i_mapping, 0, -1);
else
node_invalidate_mapping_pages(inode->i_mapping,
*(int *)nid, 0, -1);
iput(toput_inode);
toput_inode = inode;
......@@ -74,3 +84,25 @@ int drop_caches_sysctl_handler(struct ctl_table *table, int write,
}
return 0;
}
#ifdef CONFIG_SHRINK_PAGECACHE
int proc_shrink_node_caches(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int ret;
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
if (ret || !write)
return ret;
if (node_to_shrink >= MAX_NUMNODES)
return -EINVAL;
if (!node_isset(node_to_shrink, node_states[N_MEMORY]))
return 0;
iterate_supers(drop_pagecache_sb, &node_to_shrink);
return 0;
}
#endif
......@@ -2613,6 +2613,15 @@ extern bool is_bad_inode(struct inode *);
unsigned long invalidate_mapping_pages(struct address_space *mapping,
pgoff_t start, pgoff_t end);
#ifdef CONFIG_SHRINK_PAGECACHE
unsigned long node_invalidate_mapping_pages(struct address_space *mapping,
int nid, pgoff_t start, pgoff_t end);
#else
static inline unsigned long
node_invalidate_mapping_pages(struct address_space *mapping, int nid,
pgoff_t start, pgoff_t end) { return 0; }
#endif
void invalidate_mapping_pagevec(struct address_space *mapping,
pgoff_t start, pgoff_t end,
unsigned long *nr_pagevec);
......
......@@ -12,6 +12,7 @@ enum page_cache_reclaim_flag {
extern int pagecache_reclaim_enable;
extern int pagecache_limit_ratio;
extern int pagecache_reclaim_ratio;
extern int node_to_shrink;
int proc_page_cache_limit(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos);
......@@ -20,6 +21,8 @@ unsigned long __shrink_node_page_cache(int nid, gfp_t mask,
void kpagecache_limitd_stop(int nid);
int kpagecache_limitd_run(int nid);
void wakeup_all_kpagecache_limitd(void);
int proc_shrink_node_caches(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos);
#else
static inline void kpagecache_limitd_stop(int nid) {}
static inline int kpagecache_limitd_run(int nid) { return 0; }
......
......@@ -3224,6 +3224,14 @@ static struct ctl_table vm_table[] = {
.extra1 = SYSCTL_ZERO,
.extra2 = (void *)&one_hundred,
},
{
.procname = "node_drop_caches",
.data = &node_to_shrink,
.maxlen = sizeof(node_to_shrink),
.mode = 0600,
.proc_handler = proc_shrink_node_caches,
.extra1 = SYSCTL_ZERO,
},
#endif
{ }
};
......
......@@ -5,11 +5,13 @@
#include <linux/module.h>
#include <linux/err.h>
#include <linux/swap.h>
#include <linux/fs.h>
#include <linux/page_cache_limit.h>
int pagecache_reclaim_enable;
int pagecache_limit_ratio;
int pagecache_reclaim_ratio;
int node_to_shrink;
static unsigned long pagecache_limit_pages;
static unsigned long node_pagecache_limit_pages[MAX_NUMNODES];
......
......@@ -465,7 +465,7 @@ void truncate_inode_pages_final(struct address_space *mapping)
EXPORT_SYMBOL(truncate_inode_pages_final);
static unsigned long __invalidate_mapping_pages(struct address_space *mapping,
pgoff_t start, pgoff_t end, unsigned long *nr_pagevec)
pgoff_t start, pgoff_t end, unsigned long *nr_pagevec, int nid)
{
pgoff_t indices[PAGEVEC_SIZE];
struct pagevec pvec;
......@@ -487,6 +487,10 @@ static unsigned long __invalidate_mapping_pages(struct address_space *mapping,
page);
continue;
}
if (nid != NUMA_NO_NODE && page_to_nid(page) != nid)
continue;
index += thp_nr_pages(page) - 1;
ret = invalidate_inode_page(page);
......@@ -529,10 +533,34 @@ static unsigned long __invalidate_mapping_pages(struct address_space *mapping,
unsigned long invalidate_mapping_pages(struct address_space *mapping,
pgoff_t start, pgoff_t end)
{
return __invalidate_mapping_pages(mapping, start, end, NULL);
return __invalidate_mapping_pages(mapping, start, end, NULL, NUMA_NO_NODE);
}
EXPORT_SYMBOL(invalidate_mapping_pages);
/**
* node_invalidate_mapping_pages - Invalidate all the unlocked pages in @nid of one inode
* @mapping: the address_space which holds the pages to invalidate
* @nid: pages belong to this node will be invalidate
* @start: the offset 'from' which to invalidate
* @end: the offset 'to' which to invalidate (inclusive)
*
* This function only removes the unlocked pages, if you want to
* remove all the pages of one inode, you must call truncate_inode_pages.
*
* node_invalidate_mapping_pages() will not block on IO activity. It will not
* invalidate pages which are dirty, locked, under writeback or mapped into
* pagetables.
*
* Return: the number of the pages that were invalidated
*/
#ifdef CONFIG_SHRINK_PAGECACHE
unsigned long node_invalidate_mapping_pages(struct address_space *mapping,
int nid, pgoff_t start, pgoff_t end)
{
return __invalidate_mapping_pages(mapping, start, end, NULL, nid);
}
#endif
/**
* This helper is similar with the above one, except that it accounts for pages
* that are likely on a pagevec and count them in @nr_pagevec, which will used by
......@@ -541,7 +569,7 @@ EXPORT_SYMBOL(invalidate_mapping_pages);
void invalidate_mapping_pagevec(struct address_space *mapping,
pgoff_t start, pgoff_t end, unsigned long *nr_pagevec)
{
__invalidate_mapping_pages(mapping, start, end, nr_pagevec);
__invalidate_mapping_pages(mapping, start, end, nr_pagevec, NUMA_NO_NODE);
}
/*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册