
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/release-management/issues/IC9Q31 -------------------------------- Add "/proc/sys/kernel/xcall_cache_pages_order" to adjust the kernel prefetch cache buffer page's order, it can set to 0 ~ 4, that is 4KB ~ 64KB, if xcall prefetch has started, it is not allowed to update this value. Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> --- fs/eventpoll.c | 9 ++++++--- fs/proc/base.c | 33 +++++++++++++++++++++++++++++++++ include/linux/fs.h | 7 +++++++ kernel/fork.c | 1 + kernel/sysctl.c | 10 ++++++++++ 5 files changed, 57 insertions(+), 3 deletions(-) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index d34abfb3fe31..f414d9aadb66 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -777,6 +777,7 @@ DEFINE_PER_CPU_ALIGNED(unsigned long, xcall_cache_miss); static DEFINE_HASHTABLE(xcall_item_table, PREFETCH_ITEM_HASH_BITS); static DEFINE_RWLOCK(xcall_table_lock); static struct workqueue_struct *rc_work; +int cache_pages_order; static struct prefetch_item *find_prefetch_item(struct file *file) { @@ -806,7 +807,7 @@ void free_prefetch_item(struct file *file) hlist_del_init(&pfi->node); write_unlock(&xcall_table_lock); if (pfi->cache_pages) { - __free_pages(pfi->cache_pages, 0); + __free_pages(pfi->cache_pages, cache_pages_order); pfi->cache = NULL; } kfree(pfi); @@ -1352,7 +1353,8 @@ static void prefetch_work_fn(struct work_struct *work) return; pfi->len = kernel_read(pfi->file, pfi->cache, - PAGE_SIZE, &pfi->file->f_pos); + (1UL << cache_pages_order) * PAGE_SIZE, + &pfi->file->f_pos); transition_state(pfi, XCALL_CACHE_PREFETCH, XCALL_CACHE_READY); } @@ -1389,7 +1391,8 @@ static struct prefetch_item *alloc_prefetch_item(struct epitem *epi) if (!pfi) return NULL; - pfi->cache_pages = alloc_pages(GFP_KERNEL_ACCOUNT | __GFP_ZERO, 0); + pfi->cache_pages = alloc_pages(GFP_KERNEL_ACCOUNT | __GFP_ZERO, + cache_pages_order); if (!pfi->cache_pages) { kfree(pfi); return NULL; diff --git a/fs/proc/base.c b/fs/proc/base.c index fb931f4bcb6e..0799816348cc 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -3589,6 +3589,38 @@ static const struct file_operations proc_pid_sg_level_operations = { }; #endif +#ifdef CONFIG_XCALL_PREFETCH +static atomic_t epoll_wait_select_count = ATOMIC_INIT(0); +void update_epoll_wait_select_count(struct task_struct *p, + unsigned int sc_no, bool add) +{ + if (sc_no != __NR_epoll_pwait) + return; + + if (!p->xcall_select || !test_bit(sc_no, p->xcall_select)) + return; + + if (add) { + atomic_inc(&epoll_wait_select_count); + pr_info("epoll_wait_select count add: %ld, %s\n", + atomic_read(&epoll_wait_select_count), p->comm); + } else { + atomic_dec(&epoll_wait_select_count); + pr_info("epoll_wait_select count sub: %ld, %s\n", + atomic_read(&epoll_wait_select_count), p->comm); + } +} + +int proc_adjust_cache_pages_order(struct ctl_table *table, int write, + void *buffer, size_t *lenp, loff_t *ppos) +{ + if (write && atomic_read(&epoll_wait_select_count) > 0) + return -EPERM; + + return proc_dointvec_minmax(table, write, buffer, lenp, ppos); +} +#endif + #ifdef CONFIG_FAST_SYSCALL bool fast_syscall_enabled(void); @@ -3673,6 +3705,7 @@ static int xcall_select_table(struct task_struct *p, unsigned int sc_no) return -EINVAL; bitmap_set(p->xcall_select, sc_no, 1); + update_epoll_wait_select_count(p, sc_no, true); return 0; } diff --git a/include/linux/fs.h b/include/linux/fs.h index 9c27031bfea0..df3c0608aaf8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3777,13 +3777,20 @@ struct prefetch_item { DECLARE_PER_CPU_ALIGNED(unsigned long, xcall_cache_hit); DECLARE_PER_CPU_ALIGNED(unsigned long, xcall_cache_miss); +extern int cache_pages_order; int xcall_read_begin(struct file *file, unsigned int fd, char __user *buf, size_t count); void xcall_read_end(struct file *file); void free_prefetch_item(struct file *file); +int proc_adjust_cache_pages_order(struct ctl_table *table, int write, + void *buffer, size_t *lenp, loff_t *ppos); +void update_epoll_wait_select_count(struct task_struct *p, unsigned int sc_no, + bool add); #else static inline void xcall_read_end(struct file *file) {} static inline void free_prefetch_item(struct file *file) {} +static inline void update_epoll_wait_select_count(struct task_struct *p, + unsigned int sc_no, bool add) {} #endif #endif /* _LINUX_FS_H */ diff --git a/kernel/fork.c b/kernel/fork.c index b884ac9cdece..afd84458f37c 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -487,6 +487,7 @@ void free_task(struct task_struct *tsk) if (tsk->xcall_select) bitmap_free(tsk->xcall_select); #endif + update_epoll_wait_select_count(tsk, __NR_epoll_pwait, false); free_task_struct(tsk); } diff --git a/kernel/sysctl.c b/kernel/sysctl.c index b4b36f8a3149..8f07ac8c8692 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -2861,6 +2861,16 @@ static struct ctl_table kern_table[] = { .extra1 = SYSCTL_ZERO, .extra2 = &hundred_thousand, }, +#endif +#ifdef CONFIG_XCALL_PREFETCH + { .procname = "xcall_cache_pages_order", + .data = &cache_pages_order, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = proc_adjust_cache_pages_order, + .extra1 = SYSCTL_ZERO, + .extra2 = &four, + }, #endif { } }; -- 2.34.1