
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/release-management/issues/IC9Q31 -------------------------------- Xcall prefetch implements customized epoll_wait() and read() system calls, which enable data prefetching. In scenarios where the number of network connections established by a service is large, the time consumed by the service in the read() system call can be reduced. Enable $PID process xcall prefetch with following command: echo 1 > /proc/$PID/prefetch Disable $PID process xcall prefetch with following command: echo 0 > /proc/$PID/prefetch Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> --- arch/Kconfig | 17 +++++++++ arch/arm64/include/asm/xcall.h | 3 ++ arch/arm64/kernel/xcall.c | 6 +++- fs/proc/base.c | 3 ++ fs/proc/internal.h | 3 ++ fs/proc/proc_xcall.c | 66 ++++++++++++++++++++++++++++++++++ 6 files changed, 97 insertions(+), 1 deletion(-) diff --git a/arch/Kconfig b/arch/Kconfig index 6dc501a4afb1..d27eb1800cd9 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -1205,6 +1205,23 @@ config FAST_SYSCALL exception handling path that only considers necessary features such as security, context saving, and recovery. +config XCALL_PREFETCH + bool "Xcall prefetch support" + depends on FAST_SYSCALL + depends on EPOLL + default n + help + This enable xcall prefetch feature. + Xcall prefetch feature implements customized epoll_wait() and + read() system calls, which enable data prefetching. + In high-concurrency connection scenarios, this improves + the parallel execution efficiency of the read() system call + and increases the system's business throughput. + The Xcall prefetch feature is suitable for business scenarios + where the epoll I/O multiplexing mechanism is used, the read() + system call takes up a large proportion of time, and the number + of concurrent connections is large. + config ARCH_SUPPORTS_FAST_IRQ bool diff --git a/arch/arm64/include/asm/xcall.h b/arch/arm64/include/asm/xcall.h index d7e405ac3b13..f3dd439f82b7 100644 --- a/arch/arm64/include/asm/xcall.h +++ b/arch/arm64/include/asm/xcall.h @@ -8,6 +8,9 @@ struct xcall_info { /* Must be first! */ DECLARE_BITMAP(xcall_enable, __NR_syscalls); +#ifdef CONFIG_XCALL_PREFETCH + bool prefetch; +#endif }; int xcall_init_task(struct task_struct *p, struct task_struct *orig); diff --git a/arch/arm64/kernel/xcall.c b/arch/arm64/kernel/xcall.c index 9dca8729b9da..c63fa6bea3da 100644 --- a/arch/arm64/kernel/xcall.c +++ b/arch/arm64/kernel/xcall.c @@ -18,9 +18,13 @@ int xcall_init_task(struct task_struct *p, struct task_struct *orig) if (!p->xinfo) return -ENOMEM; - if (orig->xinfo) + if (orig->xinfo) { bitmap_copy(p->xinfo->xcall_enable, orig->xinfo->xcall_enable, __NR_syscalls); +#ifdef CONFIG_XCALL_PREFETCH + p->xinfo->prefetch = orig->xinfo->prefetch; +#endif + } return 0; } diff --git a/fs/proc/base.c b/fs/proc/base.c index 175c919e9f15..1788ea4e9206 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -3618,6 +3618,9 @@ static const struct pid_entry tgid_base_stuff[] = { #ifdef CONFIG_FAST_SYSCALL REG("xcall", 0644, proc_pid_xcall_operations), #endif +#ifdef CONFIG_XCALL_PREFETCH + REG("prefetch", 0644, proc_pid_xcall_prefetch_operations), +#endif #ifdef CONFIG_SCHED_AUTOGROUP REG("autogroup", S_IRUGO|S_IWUSR, proc_pid_sched_autogroup_operations), #endif diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 784f38611640..1ef6d65e5068 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -324,4 +324,7 @@ static inline void pde_force_lookup(struct proc_dir_entry *pde) #ifdef CONFIG_FAST_SYSCALL extern const struct file_operations proc_pid_xcall_operations; +#ifdef CONFIG_XCALL_PREFETCH +extern const struct file_operations proc_pid_xcall_prefetch_operations; +#endif #endif diff --git a/fs/proc/proc_xcall.c b/fs/proc/proc_xcall.c index b30dd698e057..536d719c8992 100644 --- a/fs/proc/proc_xcall.c +++ b/fs/proc/proc_xcall.c @@ -113,3 +113,69 @@ const struct file_operations proc_pid_xcall_operations = { .llseek = seq_lseek, .release = single_release, }; + +#ifdef CONFIG_XCALL_PREFETCH +static int xcall_prefetch_show(struct seq_file *m, void *v) +{ + struct inode *inode = m->private; + struct task_struct *p; + + if (!system_supports_xcall()) + return -EACCES; + + p = get_proc_task(inode); + if (!p) + return -ESRCH; + + if (p->xinfo) + seq_printf(m, "%d\n", p->xinfo->prefetch); + + put_task_struct(p); + + return 0; +} + +static int xcall_prefetch_open(struct inode *inode, struct file *filp) +{ + return single_open(filp, xcall_prefetch_show, inode); +} + +static ssize_t xcall_prefetch_write(struct file *file, const char __user *buf, + size_t count, loff_t *offset) +{ + struct inode *inode = file_inode(file); + struct task_struct *p; + char buffer[TASK_COMM_LEN]; + const size_t maxlen = sizeof(buffer) - 1; + bool prefetch_enable = true; + + if (!system_supports_xcall()) + return -EACCES; + + memset(buffer, 0, sizeof(buffer)); + if (copy_from_user(buffer, buf, count > maxlen ? maxlen : count)) + return -EFAULT; + + p = get_proc_task(inode); + if (!p) + return -ESRCH; + + if (!p->xinfo || kstrtobool(buffer, &prefetch_enable)) { + put_task_struct(p); + return -EINVAL; + } + + p->xinfo->prefetch = prefetch_enable; + put_task_struct(p); + + return count; +} + +const struct file_operations proc_pid_xcall_prefetch_operations = { + .open = xcall_prefetch_open, + .read = seq_read, + .write = xcall_prefetch_write, + .llseek = seq_lseek, + .release = single_release, +}; +#endif -- 2.34.1