hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9GZAQ CVE: NA
--------------------------------
Introduce bpf helper to get task relationship. Now, can get some relationship data for memory share and network communication.
Signed-off-by: Hui Tang tanghui20@huawei.com --- include/linux/sched/relationship.h | 28 ++++++++++++++++++++++++++++ include/uapi/linux/bpf.h | 7 +++++++ kernel/sched/bpf_sched.c | 29 +++++++++++++++++++++++++++++ kernel/sched/fair.c | 26 ++++++++++++++++++++++++++ kernel/sched/relationship.c | 22 ++++++++++++++++++++++ scripts/bpf_helpers_doc.py | 2 ++ tools/include/uapi/linux/bpf.h | 7 +++++++ 7 files changed, 121 insertions(+)
diff --git a/include/linux/sched/relationship.h b/include/linux/sched/relationship.h index df3f3f7814cd..f603ed71e3e4 100644 --- a/include/linux/sched/relationship.h +++ b/include/linux/sched/relationship.h @@ -20,6 +20,30 @@ struct fault_array_info { unsigned long val; };
+struct relationship_comm { + int nr_tasks; + int gid; + nodemask_t preferred_node; +}; + +struct bpf_net_relationship { + struct relationship_comm comm; + unsigned long grp_rxtx_bytes; + unsigned long grp_remote_rxtx_bytes; +}; + +struct bpf_mm_relationship { + struct relationship_comm comm; + unsigned long grp_total_faults; + struct fault_array_info grp_faults_ordered[FAULT_NODES_MAX]; + struct fault_array_info grp_score_ordered[FAULT_NODES_MAX]; +}; + +struct bpf_relationship_get_args { + struct bpf_mm_relationship mm; + struct bpf_net_relationship net; +}; + struct relationship_hdr { refcount_t refcount; spinlock_t lock; @@ -103,6 +127,10 @@ extern void sched_relationship_free(struct task_struct *p); void task_relationship_free(struct task_struct *tsk, bool reset); extern bool task_relationship_supported(struct task_struct *tsk); extern int sched_net_relationship_submit(struct net_relationship_req *req); +extern void sched_get_mm_relationship(struct task_struct *tsk, + struct bpf_relationship_get_args *args); +extern void sched_get_relationship(struct task_struct *tsk, + struct bpf_relationship_get_args *args); extern void numa_faults_update_and_sort(int nid, int new, struct fault_array_info *stats);
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index e608b32d4c5a..1274fe6d3ab8 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -3902,6 +3902,12 @@ union bpf_attr { * set online nodes to nodemask_t *op->arg1*, 0 returned. * Return * View above. + * + * int bpf_get_task_relationship_stats(struct task_struct *tsk, struct bpf_map *map, struct bpf_relationship_get_args *stats) + * Description + * get relationship statistics of *tsk* and store in *stats*. + * Return + * 0 on success, or a negative error in case of failure. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -4075,6 +4081,7 @@ union bpf_attr { FN(cpumask_op), \ FN(cpus_share_cache), \ FN(nodemask_op), \ + FN(get_task_relationship_stats),\ /* */
/* integer value in 'imm' field of BPF_CALL instruction selects which helper diff --git a/kernel/sched/bpf_sched.c b/kernel/sched/bpf_sched.c index a1e72533d5b6..3cff265526b2 100644 --- a/kernel/sched/bpf_sched.c +++ b/kernel/sched/bpf_sched.c @@ -346,6 +346,31 @@ static const struct bpf_func_proto bpf_cpus_share_cache_proto = { .arg2_type = ARG_ANYTHING, };
+#ifdef CONFIG_SCHED_TASK_RELATIONSHIP +BPF_CALL_3(bpf_get_task_relationship_stats, struct task_struct *, tsk, + struct bpf_map *, map, struct bpf_relationship_get_args *, args) +{ + if (!task_relationship_supported(tsk)) + return -EPERM; + + if (!args) + return -EINVAL; + + sched_get_relationship(tsk, args); + return 0; +} + +const struct bpf_func_proto bpf_get_task_relationship_stats_proto = { + .func = bpf_get_task_relationship_stats, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_BTF_ID, + .arg1_btf_id = &btf_sched_task_ids[0], + .arg2_type = ARG_CONST_MAP_PTR, + .arg3_type = ARG_PTR_TO_MAP_VALUE_OR_NULL, +}; +#endif + static const struct bpf_func_proto * bpf_sched_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) { @@ -370,6 +395,10 @@ bpf_sched_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_cpus_share_cache_proto; case BPF_FUNC_nodemask_op: return &bpf_nodemask_op_proto; +#ifdef CONFIG_SCHED_TASK_RELATIONSHIP + case BPF_FUNC_get_task_relationship_stats: + return &bpf_get_task_relationship_stats_proto; +#endif default: return bpf_base_func_proto(func_id); } diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 7a705a882a64..5ec1acb809ed 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3042,6 +3042,32 @@ static inline void update_scan_period(struct task_struct *p, int new_cpu)
#endif /* CONFIG_NUMA_BALANCING */
+#ifdef CONFIG_SCHED_TASK_RELATIONSHIP + +#ifdef CONFIG_BPF_SCHED +void sched_get_mm_relationship(struct task_struct *tsk, + struct bpf_relationship_get_args *args) +{ +#ifdef CONFIG_NUMA_BALANCING + struct numa_group *grp; + + grp = rcu_dereference(tsk->numa_group); + if (grp) { + args->mm.comm.gid = grp->gid; + args->mm.comm.nr_tasks = grp->nr_tasks; + args->mm.grp_total_faults = grp->total_faults; + args->mm.comm.preferred_node = grp->preferred_nid; + memcpy(args->mm.grp_faults_ordered, grp->faults_ordered, + sizeof(args->mm.grp_faults_ordered)); + memcpy(args->mm.grp_score_ordered, grp->score_ordered, + sizeof(args->mm.grp_score_ordered)); + } +#endif +} +#endif + +#endif + #ifdef CONFIG_QOS_SCHED_PRIO_LB static __always_inline void adjust_rq_cfs_tasks(void (*list_op)(struct list_head *, struct list_head *), diff --git a/kernel/sched/relationship.c b/kernel/sched/relationship.c index 01879e3272de..89feb4b218d4 100644 --- a/kernel/sched/relationship.c +++ b/kernel/sched/relationship.c @@ -344,6 +344,28 @@ void numa_faults_update_and_sort(int nid, int new, sort(stats, nodes, sizeof(stats[0]), cmp_fault_stats, NULL); }
+void sched_get_relationship(struct task_struct *tsk, + struct bpf_relationship_get_args *args) +{ + struct net_group *ngrp; + + rcu_read_lock(); + + /* memory relationship */ + sched_get_mm_relationship(tsk, args); + + /* net relationship */ + ngrp = rcu_dereference(tsk->rship->net_group); + if (ngrp) { + args->net.comm.gid = ngrp->hdr.gid; + args->net.comm.nr_tasks = ngrp->hdr.nr_tasks; + args->net.comm.preferred_node = ngrp->hdr.preferred_nid; + args->net.grp_rxtx_bytes = ngrp->rxtx_bytes; + } + + rcu_read_unlock(); +} + void task_relationship_free(struct task_struct *tsk, bool reset) { if (!task_relationship_used()) diff --git a/scripts/bpf_helpers_doc.py b/scripts/bpf_helpers_doc.py index 929a3031b4d6..db43107ba6f0 100755 --- a/scripts/bpf_helpers_doc.py +++ b/scripts/bpf_helpers_doc.py @@ -446,6 +446,7 @@ class PrinterHelpers(Printer): 'struct sched_affine_ctx', 'struct sched_migrate_node', 'struct nodemask_op_args', + 'struct bpf_relationship_get_args', ] known_types = { '...', @@ -500,6 +501,7 @@ class PrinterHelpers(Printer): 'struct sched_affine_ctx', 'struct sched_migrate_node', 'struct nodemask_op_args', + 'struct bpf_relationship_get_args', } mapped_types = { 'u8': '__u8', diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 809723603ba8..ac08b57826a2 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -3902,6 +3902,12 @@ union bpf_attr { * set online nodes to nodemask_t *op->arg1*, 0 returned. * Return * View above. + * + * int bpf_get_task_relationship_stats(struct task_struct *tsk, struct bpf_map *map, struct bpf_relationship_get_args *stats) + * Description + * get relationship statistics of *tsk* and store in *stats*. + * Return + * 0 on success, or a negative error in case of failure. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -4075,6 +4081,7 @@ union bpf_attr { FN(cpumask_op), \ FN(cpus_share_cache), \ FN(nodemask_op), \ + FN(get_task_relationship_stats),\ /* */
/* integer value in 'imm' field of BPF_CALL instruction selects which helper