Unverified Commit 2e7cbc38 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!4070 Backport etmem feature to OLK 6.6

Merge Pull Request from: @ci-robot 
 
PR sync from: Yuchen Tang <tangyuchen5@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/YX3ELZWBNV3H6DYZW67I4JTVHJAM2YOU/ 
v4 -> v5
- fix redundant kvm config check

v3 -> v4
- backport only core etmem feature
- modify kernel swap enabled toggle implementation

v2 -> v3
- fix code style and commit messages

v1 -> v2
- make independent patches to export symbols we need
- make independent patches for etmem scan and swap config
- fix indentation and code style problems

Yuchen Tang (9):
  etmem: add ETMEM feature CONFIG to mm/Kconfig
  etmem: add ETMEM scan feature CONFIG to mm/Kconfig
  mm: Export symbol __pud_trans_huge_lock
  mm: Export symbol walk_page_range
  etmem: add etmem scan feature
  mm: Export symbol reclaim_pages
  etmem: add etmem swap feature
  etmem: add original kernel swap enabled options
  etmem: enable etmem configurations


-- 
2.33.0
 
https://gitee.com/openeuler/kernel/issues/I4QVXW
https://gitee.com/openeuler/kernel/issues/I8T1MB?from=project-issue 
 
Link:https://gitee.com/openeuler/kernel/pulls/4070

 

Reviewed-by: default avatarKefeng Wang <wangkefeng.wang@huawei.com>
Reviewed-by: default avatarZucheng Zheng <zhengzucheng@huawei.com>
Reviewed-by: default avatarLiu Chao <liuchao173@huawei.com>
Reviewed-by: default avatarWeilong Chen <chenweilong@huawei.com>
Reviewed-by: default avatarzhangyi (F) <yi.zhang@huawei.com>
Reviewed-by: default avatarKevin Zhu <zhukeqian1@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parents e9cf41a4 0599b897
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1153,6 +1153,9 @@ CONFIG_PER_VMA_LOCK=y
CONFIG_LOCK_MM_AND_FIND_VMA=y
CONFIG_MEMORY_RELIABLE=y
CONFIG_DYNAMIC_POOL=y
CONFIG_ETMEM_SCAN=m
CONFIG_ETMEM_SWAP=m
CONFIG_ETMEM=y

#
# Data Access Monitoring
+3 −0
Original line number Diff line number Diff line
@@ -1168,6 +1168,9 @@ CONFIG_ARCH_SUPPORTS_PER_VMA_LOCK=y
CONFIG_PER_VMA_LOCK=y
CONFIG_LOCK_MM_AND_FIND_VMA=y
CONFIG_DYNAMIC_POOL=y
CONFIG_ETMEM_SCAN=m
CONFIG_ETMEM_SWAP=m
CONFIG_ETMEM=y

#
# Data Access Monitoring
+3 −0
Original line number Diff line number Diff line
@@ -35,3 +35,6 @@ proc-$(CONFIG_PRINTK) += kmsg.o
proc-$(CONFIG_PROC_PAGE_MONITOR)	+= page.o
proc-$(CONFIG_BOOT_CONFIG)	+= bootconfig.o
proc-$(CONFIG_MEMORY_RELIABLE)	+= mem_reliable.o
obj-$(CONFIG_ETMEM_SCAN)	+= etmem_scan.o
obj-$(CONFIG_ETMEM_SWAP)	+= etmem_swap.o
proc-${CONFIG_ETMEM}		+= etmem_proc.o
+8 −0
Original line number Diff line number Diff line
@@ -3366,6 +3366,10 @@ static const struct pid_entry tgid_base_stuff[] = {
	REG("smaps_rollup", S_IRUGO, proc_pid_smaps_rollup_operations),
	REG("pagemap",    S_IRUSR, proc_pagemap_operations),
#endif
#ifdef CONFIG_ETMEM
	REG("idle_pages", S_IRUSR|S_IWUSR, proc_mm_idle_operations),
	REG("swap_pages", S_IWUSR, proc_mm_swap_operations),
#endif
#ifdef CONFIG_SECURITY
	DIR("attr",       S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
#endif
@@ -3776,6 +3780,10 @@ static const struct pid_entry tid_base_stuff[] = {
	REG("smaps_rollup", S_IRUGO, proc_pid_smaps_rollup_operations),
	REG("pagemap",    S_IRUSR, proc_pagemap_operations),
#endif
#ifdef CONFIG_ETMEM
	REG("idle_pages", S_IRUSR|S_IWUSR, proc_mm_idle_operations),
	REG("swap_pages", S_IWUSR, proc_mm_swap_operations),
#endif
#ifdef CONFIG_SECURITY
	DIR("attr",      S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
#endif

fs/proc/etmem_proc.c

0 → 100644
+216 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
#include <linux/seq_file.h>
#include <linux/pagemap.h>
#include <linux/mempolicy.h>
#include <linux/swap.h>
#include <linux/sched/mm.h>
#include <linux/mmu_notifier.h>
#include <linux/page_idle.h>
#include <linux/uaccess.h>
#include <linux/pkeys.h>
#include <linux/module.h>
#include <linux/ptrace.h>
#include <linux/etmem.h>

#include "internal.h"

static DEFINE_SPINLOCK(scan_lock);

static int page_scan_lock(struct file *file, int is_lock, struct file_lock *flock)
{
	if (is_lock)
		spin_lock(&scan_lock);
	else
		spin_unlock(&scan_lock);

	return 0;
}

/* will be filled when kvm_ept_idle module loads */
struct file_operations proc_page_scan_operations = {
	.flock = page_scan_lock,
};
EXPORT_SYMBOL_GPL(proc_page_scan_operations);

static ssize_t mm_idle_read(struct file *file, char __user *buf,
			    size_t count, loff_t *ppos)
{
	struct mm_struct *mm = file->private_data;
	int ret = 0;

	if (!mm || !mmget_not_zero(mm)) {
		ret = -ESRCH;
		return ret;
	}
	if (proc_page_scan_operations.read)
		ret = proc_page_scan_operations.read(file, buf, count, ppos);

	mmput(mm);
	return ret;
}

static int mm_idle_open(struct inode *inode, struct file *file)
{
	struct mm_struct *mm = NULL;
	struct module *module = NULL;
	int ret = -1;

	if (!file_ns_capable(file, &init_user_ns, CAP_SYS_ADMIN))
		return -EPERM;

	page_scan_lock(NULL, 1, NULL);
	module = proc_page_scan_operations.owner;
	if (module != NULL && try_module_get(module))
		ret = 0;
	page_scan_lock(NULL, 0, NULL);
	if (ret != 0) {
		/* no scan ko installed, avoid to return valid file */
		return -ENODEV;
	}

	mm = proc_mem_open(inode, PTRACE_MODE_READ);
	if (IS_ERR(mm)) {
		module_put(module);
		return PTR_ERR(mm);
	}

	file->private_data = mm;

	if (proc_page_scan_operations.open)
		ret = proc_page_scan_operations.open(inode, file);

	if (ret != 0)
		module_put(module);

	return ret;
}

static int mm_idle_release(struct inode *inode, struct file *file)
{
	struct mm_struct *mm = file->private_data;
	int ret = 0;

	if (mm) {
		if (!mm_kvm(mm))
			flush_tlb_mm(mm);
		mmdrop(mm);
	}

	if (proc_page_scan_operations.release)
		ret = proc_page_scan_operations.release(inode, file);

	if (proc_page_scan_operations.owner)
		module_put(proc_page_scan_operations.owner);

	return ret;
}

static long mm_idle_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	if (proc_page_scan_operations.unlocked_ioctl)
		return proc_page_scan_operations.unlocked_ioctl(filp, cmd, arg);

	return 0;
}

const struct file_operations proc_mm_idle_operations = {
	.llseek		= mem_lseek, /* borrow this */
	.read		= mm_idle_read,
	.open		= mm_idle_open,
	.release	= mm_idle_release,
	.unlocked_ioctl = mm_idle_ioctl,
};

static DEFINE_SPINLOCK(swap_lock);

static int page_swap_lock(struct file *file, int is_lock, struct file_lock *flock)
{
	if (is_lock)
		spin_lock(&swap_lock);
	else
		spin_unlock(&swap_lock);

	return 0;
}
/*swap pages*/
struct file_operations proc_swap_pages_operations = {
	.flock = page_swap_lock,
};
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;
	struct module *module = NULL;
	int ret = -1;

	if (!file_ns_capable(file, &init_user_ns, CAP_SYS_ADMIN))
		return -EPERM;

	page_swap_lock(NULL, 1, NULL);
	module = proc_swap_pages_operations.owner;
	if (module != NULL && try_module_get(module))
		ret = 0;
	page_swap_lock(NULL, 0, NULL);
	if (ret != 0) {
		/* no swap ko installed, avoid to return valid file */
		return -ENODEV;
	}

	mm = proc_mem_open(inode, PTRACE_MODE_READ);
	if (IS_ERR(mm)) {
		module_put(module);
		return PTR_ERR(mm);
	}

	file->private_data = mm;

	if (proc_swap_pages_operations.open)
		ret = proc_swap_pages_operations.open(inode, file);

	if (ret != 0)
		module_put(module);

	return ret;
}

static int mm_swap_release(struct inode *inode, struct file *file)
{
	struct mm_struct *mm = file->private_data;
	int ret = 0;

	if (mm)
		mmdrop(mm);

	if (proc_swap_pages_operations.release)
		ret = proc_swap_pages_operations.release(inode, file);

	if (proc_swap_pages_operations.owner)
		module_put(proc_swap_pages_operations.owner);

	return ret;
}

static long mm_swap_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	if (proc_swap_pages_operations.unlocked_ioctl)
		return proc_swap_pages_operations.unlocked_ioctl(filp, cmd, arg);
	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,
	.unlocked_ioctl = mm_swap_ioctl,
};
Loading