You need to sign in or sign up before continuing.
提交 fb3893e8 编写于 作者: L liubo 提交者: Cheng Jian

etmem: add etmem-swap feature

euleros inclusion
category: feature
feature: etmem
bugzilla: 49889

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

In order to achieve the goal of memory expansion,
cold pages need to be migrated to the swap partition,
etmem_swap.ko is to achieve this purpose.

This patch is mainly used to generate etmem_swap.ko.
etmem_swap.ko is used to transfer the address
passed in the user state for page migration.
Signed-off-by: Nyanxiaodan <yanxiaodan@huawei.com>
Signed-off-by: Nlinmiaohe <linmiaohe@huawei.com>
Signed-off-by: Nlouhongxiang <louhongxiang@huawei.com>
Signed-off-by: Nliubo <liubo254@huawei.com>
Signed-off-by: Ngeruijun <geruijun@huawei.com>
Signed-off-by: Nliangchenshu <liangchenshu@huawei.com>
Acked-by: NXie XiuQi <xiexiuqi@huawei.com>
Reviewed-by: Jing Xiangfeng<jingxiangfeng@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: NCheng Jian <cj.chengjian@huawei.com>
上级 bad4d883
...@@ -34,3 +34,4 @@ proc-$(CONFIG_PROC_VMCORE) += vmcore.o ...@@ -34,3 +34,4 @@ proc-$(CONFIG_PROC_VMCORE) += vmcore.o
proc-$(CONFIG_PRINTK) += kmsg.o proc-$(CONFIG_PRINTK) += kmsg.o
proc-$(CONFIG_PROC_PAGE_MONITOR) += page.o proc-$(CONFIG_PROC_PAGE_MONITOR) += page.o
obj-$(CONFIG_ETMEM_SCAN) += etmem_scan.o obj-$(CONFIG_ETMEM_SCAN) += etmem_scan.o
obj-$(CONFIG_ETMEM_SWAP) += etmem_swap.o
...@@ -2989,6 +2989,7 @@ static const struct pid_entry tgid_base_stuff[] = { ...@@ -2989,6 +2989,7 @@ static const struct pid_entry tgid_base_stuff[] = {
REG("smaps_rollup", S_IRUGO, proc_pid_smaps_rollup_operations), REG("smaps_rollup", S_IRUGO, proc_pid_smaps_rollup_operations),
REG("pagemap", S_IRUSR, proc_pagemap_operations), REG("pagemap", S_IRUSR, proc_pagemap_operations),
REG("idle_pages", S_IRUSR|S_IWUSR, proc_mm_idle_operations), REG("idle_pages", S_IRUSR|S_IWUSR, proc_mm_idle_operations),
REG("swap_pages", S_IWUSR, proc_mm_swap_operations),
#endif #endif
#ifdef CONFIG_SECURITY #ifdef CONFIG_SECURITY
DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations), DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
...@@ -3375,6 +3376,7 @@ static const struct pid_entry tid_base_stuff[] = { ...@@ -3375,6 +3376,7 @@ static const struct pid_entry tid_base_stuff[] = {
REG("smaps_rollup", S_IRUGO, proc_pid_smaps_rollup_operations), REG("smaps_rollup", S_IRUGO, proc_pid_smaps_rollup_operations),
REG("pagemap", S_IRUSR, proc_pagemap_operations), REG("pagemap", S_IRUSR, proc_pagemap_operations),
REG("idle_pages", S_IRUSR|S_IWUSR, proc_mm_idle_operations), REG("idle_pages", S_IRUSR|S_IWUSR, proc_mm_idle_operations),
REG("swap_pages", S_IWUSR, proc_mm_swap_operations),
#endif #endif
#ifdef CONFIG_SECURITY #ifdef CONFIG_SECURITY
DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations), DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
......
// SPDX-License-Identifier: GPL-2.0
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/proc_fs.h>
#include <linux/sched/mm.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/mempolicy.h>
#include <linux/uaccess.h>
#include <linux/delay.h>
static ssize_t swap_pages_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
char *p, *data, *data_ptr_res;
unsigned long vaddr;
struct mm_struct *mm = file->private_data;
struct page *page;
LIST_HEAD(pagelist);
int ret = 0;
if (!mm || !mmget_not_zero(mm)) {
ret = -ESRCH;
goto out;
}
if (count < 0) {
ret = -EOPNOTSUPP;
goto out_mm;
}
data = memdup_user_nul(buf, count);
if (IS_ERR(data)) {
ret = PTR_ERR(data);
goto out_mm;
}
data_ptr_res = data;
while ((p = strsep(&data, "\n")) != NULL) {
if (!*p)
continue;
ret = kstrtoul(p, 16, &vaddr);
if (ret != 0)
continue;
/*If get page struct failed, ignore it, get next page*/
page = get_page_from_vaddr(mm, vaddr);
if (!page)
continue;
add_page_for_swap(page, &pagelist);
}
if (!list_empty(&pagelist))
reclaim_pages(&pagelist);
ret = count;
kfree(data_ptr_res);
out_mm:
mmput(mm);
out:
return ret;
}
static int swap_pages_open(struct inode *inode, struct file *file)
{
if (!try_module_get(THIS_MODULE))
return -EBUSY;
return 0;
}
static int swap_pages_release(struct inode *inode, struct file *file)
{
module_put(THIS_MODULE);
return 0;
}
extern struct file_operations proc_swap_pages_operations;
static int swap_pages_entry(void)
{
proc_swap_pages_operations.owner = THIS_MODULE;
proc_swap_pages_operations.write = swap_pages_write;
proc_swap_pages_operations.open = swap_pages_open;
proc_swap_pages_operations.release = swap_pages_release;
return 0;
}
static void swap_pages_exit(void)
{
memset(&proc_swap_pages_operations, 0,
sizeof(proc_swap_pages_operations));
}
MODULE_LICENSE("GPL");
module_init(swap_pages_entry);
module_exit(swap_pages_exit);
...@@ -300,6 +300,7 @@ extern const struct file_operations proc_pid_smaps_rollup_operations; ...@@ -300,6 +300,7 @@ extern const struct file_operations proc_pid_smaps_rollup_operations;
extern const struct file_operations proc_clear_refs_operations; extern const struct file_operations proc_clear_refs_operations;
extern const struct file_operations proc_pagemap_operations; extern const struct file_operations proc_pagemap_operations;
extern const struct file_operations proc_mm_idle_operations; extern const struct file_operations proc_mm_idle_operations;
extern const struct file_operations proc_mm_swap_operations;
extern unsigned long task_vsize(struct mm_struct *); extern unsigned long task_vsize(struct mm_struct *);
extern unsigned long task_statm(struct mm_struct *, extern unsigned long task_statm(struct mm_struct *,
......
...@@ -1663,7 +1663,58 @@ const struct file_operations proc_mm_idle_operations = { ...@@ -1663,7 +1663,58 @@ const struct file_operations proc_mm_idle_operations = {
.release = mm_idle_release, .release = mm_idle_release,
}; };
/*swap pages*/
struct file_operations proc_swap_pages_operations = {
};
EXPORT_SYMBOL_GPL(proc_swap_pages_operations);
static ssize_t mm_swap_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
if (proc_swap_pages_operations.write)
return proc_swap_pages_operations.write(file, buf, count, ppos);
return -1;
}
static int mm_swap_open(struct inode *inode, struct file *file)
{
struct mm_struct *mm = NULL;
if (!file_ns_capable(file, &init_user_ns, CAP_SYS_ADMIN))
return -EPERM;
mm = proc_mem_open(inode, PTRACE_MODE_READ);
if (IS_ERR(mm))
return PTR_ERR(mm);
file->private_data = mm;
if (proc_swap_pages_operations.open)
return proc_swap_pages_operations.open(inode, file);
return 0;
}
static int mm_swap_release(struct inode *inode, struct file *file)
{
struct mm_struct *mm = file->private_data;
if (mm)
mmdrop(mm);
if (proc_swap_pages_operations.release)
return proc_swap_pages_operations.release(inode, file);
return 0;
}
const struct file_operations proc_mm_swap_operations = {
.llseek = mem_lseek,
.write = mm_swap_write,
.open = mm_swap_open,
.release = mm_swap_release,
};
#endif /* CONFIG_PROC_PAGE_MONITOR */ #endif /* CONFIG_PROC_PAGE_MONITOR */
#ifdef CONFIG_NUMA #ifdef CONFIG_NUMA
......
...@@ -374,6 +374,11 @@ extern int vm_swappiness; ...@@ -374,6 +374,11 @@ extern int vm_swappiness;
extern int remove_mapping(struct address_space *mapping, struct page *page); extern int remove_mapping(struct address_space *mapping, struct page *page);
extern unsigned long vm_total_pages; extern unsigned long vm_total_pages;
extern unsigned long reclaim_pages(struct list_head *page_list);
extern int add_page_for_swap(struct page *page, struct list_head *pagelist);
extern struct page *get_page_from_vaddr(struct mm_struct *mm,
unsigned long vaddr);
#ifdef CONFIG_SHRINK_PAGECACHE #ifdef CONFIG_SHRINK_PAGECACHE
extern unsigned long vm_cache_limit_ratio; extern unsigned long vm_cache_limit_ratio;
extern unsigned long vm_cache_limit_ratio_min; extern unsigned long vm_cache_limit_ratio_min;
......
...@@ -605,6 +605,11 @@ config ETMEM_SCAN ...@@ -605,6 +605,11 @@ config ETMEM_SCAN
etmem page scan feature etmem page scan feature
used to scan the virtual address of the target process used to scan the virtual address of the target process
config ETMEM_SWAP
tristate "module: etmem page swap for etmem support"
help
etmem page swap feature
config STRING_SELFTEST config STRING_SELFTEST
tristate "Test string functions" tristate "Test string functions"
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/topology.h> #include <linux/topology.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/cpuset.h> #include <linux/cpuset.h>
#include <linux/mempolicy.h>
#include <linux/compaction.h> #include <linux/compaction.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/rwsem.h> #include <linux/rwsem.h>
...@@ -4401,3 +4402,114 @@ void check_move_unevictable_pages(struct page **pages, int nr_pages) ...@@ -4401,3 +4402,114 @@ void check_move_unevictable_pages(struct page **pages, int nr_pages)
} }
} }
#endif /* CONFIG_SHMEM */ #endif /* CONFIG_SHMEM */
unsigned long reclaim_pages(struct list_head *page_list)
{
int nid = NUMA_NO_NODE;
unsigned long nr_reclaimed = 0;
LIST_HEAD(node_page_list);
struct reclaim_stat dummy_stat;
struct page *page;
struct scan_control sc = {
.gfp_mask = GFP_KERNEL,
.priority = DEF_PRIORITY,
.may_writepage = 1,
.may_unmap = 1,
.may_swap = 1,
};
while (!list_empty(page_list)) {
page = lru_to_page(page_list);
if (nid == NUMA_NO_NODE) {
nid = page_to_nid(page);
INIT_LIST_HEAD(&node_page_list);
}
if (nid == page_to_nid(page)) {
ClearPageActive(page);
list_move(&page->lru, &node_page_list);
continue;
}
nr_reclaimed += shrink_page_list(&node_page_list,
NODE_DATA(nid),
&sc, 0,
&dummy_stat, false);
while (!list_empty(&node_page_list)) {
page = lru_to_page(&node_page_list);
list_del(&page->lru);
putback_lru_page(page);
}
nid = NUMA_NO_NODE;
}
if (!list_empty(&node_page_list)) {
nr_reclaimed += shrink_page_list(&node_page_list,
NODE_DATA(nid),
&sc, 0,
&dummy_stat, false);
while (!list_empty(&node_page_list)) {
page = lru_to_page(&node_page_list);
list_del(&page->lru);
putback_lru_page(page);
}
}
return nr_reclaimed;
}
EXPORT_SYMBOL_GPL(reclaim_pages);
int add_page_for_swap(struct page *page, struct list_head *pagelist)
{
int err = -EBUSY;
struct page *head;
/*If the page is mapped by more than one process, do not swap it */
if (page_mapcount(page) > 1)
return -EACCES;
if (PageHuge(page))
return -EACCES;
head = compound_head(page);
err = isolate_lru_page(head);
if (err) {
put_page(page);
return err;
}
put_page(page);
if (PageUnevictable(page))
putback_lru_page(page);
else
list_add_tail(&head->lru, pagelist);
err = 0;
return err;
}
EXPORT_SYMBOL_GPL(add_page_for_swap);
struct page *get_page_from_vaddr(struct mm_struct *mm, unsigned long vaddr)
{
struct page *page;
struct vm_area_struct *vma;
unsigned int follflags;
down_read(&mm->mmap_sem);
vma = find_vma(mm, vaddr);
if (!vma || vaddr < vma->vm_start || vma->vm_flags & VM_LOCKED) {
up_read(&mm->mmap_sem);
return NULL;
}
follflags = FOLL_GET | FOLL_DUMP;
page = follow_page(vma, vaddr, follflags);
if (IS_ERR(page) || !page) {
up_read(&mm->mmap_sem);
return NULL;
}
up_read(&mm->mmap_sem);
return page;
}
EXPORT_SYMBOL_GPL(get_page_from_vaddr);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册