Commit 13515974 authored by Hui Tang's avatar Hui Tang
Browse files

bpf:programmable: Add helper to get memory and net relationship

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: default avatarHui Tang <tanghui20@huawei.com>
parent 2ac826b2
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -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);

+7 −0
Original line number Diff line number Diff line
@@ -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
+29 −0
Original line number Diff line number Diff line
@@ -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);
	}
+26 −0
Original line number Diff line number Diff line
@@ -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 *),
+22 −0
Original line number Diff line number Diff line
@@ -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())
Loading