
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/release-management/issues/IC9Q31 -------------------------------- Add "/proc/xcall/numa_mask" to adjust the kernel async prefetch cpu range, default set to the numa cpumask, use following cmd to set the cpu range: echo "$numa0_mask: ... :$numa${n}_mask" > /proc/xcall/numa_mask Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> --- fs/eventpoll.c | 5 ++ fs/proc/base.c | 112 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 6 +++ 3 files changed, 123 insertions(+) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index f414d9aadb66..68b666d08df7 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1361,8 +1361,13 @@ static void prefetch_work_fn(struct work_struct *work) static void set_prefetch_numa_cpu(struct prefetch_item *pfi, int fd) { int cpu = smp_processor_id(); + int node = numa_node_id(); cpumask_and(&pfi->related_cpus, cpu_cpu_mask(cpu), cpu_online_mask); + mutex_lock(&xcall_numa_entries[node].lock); + cpumask_and(&pfi->related_cpus, &pfi->related_cpus, + xcall_numa_entries[node].mask); + mutex_unlock(&xcall_numa_entries[node].lock); pfi->cpu = cpumask_next(fd % cpumask_weight(&pfi->related_cpus), &pfi->related_cpus); } diff --git a/fs/proc/base.c b/fs/proc/base.c index 0799816348cc..a759c660e8bf 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -3818,6 +3818,115 @@ static const struct proc_ops xcall_stats_fops = { .proc_release = single_release }; +struct numa_mask_entry *xcall_numa_entries; +static int nr_numa_nodes; + +static ssize_t xcall_numa_masks_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + char *input, *token, *tmp; + struct cpumask tmp_mask; + int node, ret = 0; + + input = kzalloc(count + 1, GFP_KERNEL); + if (!input) + return -ENOMEM; + + if (copy_from_user(input, buf, count)) { + ret = -EFAULT; + goto out; + } + + input[count] = '\0'; + tmp = input; + + for_each_online_node(node) { + token = strsep(&tmp, ":"); + if (!token || node >= nr_numa_nodes) { + ret = -EINVAL; + goto out; + } + + if (cpulist_parse(token, &tmp_mask)) { + ret = -EINVAL; + goto out; + } + cpumask_and(&tmp_mask, &tmp_mask, cpumask_of_node(node)); + if (cpumask_empty(&tmp_mask)) { + ret = -EINVAL; + goto out; + } + + mutex_lock(&xcall_numa_entries[node].lock); + cpumask_copy(xcall_numa_entries[node].mask, &tmp_mask); + mutex_unlock(&xcall_numa_entries[node].lock); + } + +out: + kfree(input); + return ret ? ret : count; +} + +static ssize_t xcall_numa_masks_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + char *output, *tmp; + int node, ret = 0; + size_t len = 0; + + tmp = kzalloc(num_possible_cpus() * 5, GFP_KERNEL); + output = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!output) + return -ENOMEM; + + for_each_online_node(node) { + mutex_lock(&xcall_numa_entries[node].lock); + cpumap_print_to_pagebuf(true, tmp, xcall_numa_entries[node].mask); + mutex_unlock(&xcall_numa_entries[node].lock); + + len += scnprintf(output + len, PAGE_SIZE - len, + "numa %d: %s", node, tmp); + if (len >= PAGE_SIZE) + break; + } + + ret = simple_read_from_buffer(buf, count, ppos, output, len); + kfree(output); + kfree(tmp); + return ret; +} + +static const struct proc_ops xcall_numa_mask_fops = { + .proc_read = xcall_numa_masks_read, + .proc_write = xcall_numa_masks_write, +}; + +static int __init xcall_numa_masks_init(void) +{ + int node; + + nr_numa_nodes = nr_online_nodes; + xcall_numa_entries = kcalloc(nr_numa_nodes, sizeof(*xcall_numa_entries), + GFP_KERNEL); + if (!xcall_numa_entries) + return -ENOMEM; + + for_each_online_node(node) { + if (!alloc_cpumask_var(&xcall_numa_entries[node].mask, GFP_KERNEL)) + goto err_free; + cpumask_copy(xcall_numa_entries[node].mask, cpumask_of_node(node)); + mutex_init(&xcall_numa_entries[node].lock); + } + + return 0; + +err_free: + while (--node >= 0) + free_cpumask_var(xcall_numa_entries[node].mask); + kfree(xcall_numa_entries); + return -ENOMEM; +} + static int __init init_xcall_stats_procfs(void) { struct proc_dir_entry *xcall_proc_dir; @@ -3827,6 +3936,9 @@ static int __init init_xcall_stats_procfs(void) xcall_proc_dir = proc_mkdir("xcall", NULL); proc_create("stats", 0444, xcall_proc_dir, &xcall_stats_fops); + proc_create("numa_mask", 0644, xcall_proc_dir, &xcall_numa_mask_fops); + xcall_numa_masks_init(); + return 0; } device_initcall(init_xcall_stats_procfs); diff --git a/include/linux/fs.h b/include/linux/fs.h index df3c0608aaf8..86fc23c96c31 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3774,10 +3774,16 @@ struct prefetch_item { struct hlist_node node; }; +struct numa_mask_entry { + cpumask_var_t mask; + struct mutex lock; +}; + DECLARE_PER_CPU_ALIGNED(unsigned long, xcall_cache_hit); DECLARE_PER_CPU_ALIGNED(unsigned long, xcall_cache_miss); extern int cache_pages_order; +extern struct numa_mask_entry *xcall_numa_entries; int xcall_read_begin(struct file *file, unsigned int fd, char __user *buf, size_t count); void xcall_read_end(struct file *file); -- 2.34.1