bpf: Implement link_query for bpf iterators
This patch implemented bpf_link callback functions show_fdinfo and fill_link_info to support link_query interface. The general interface for show_fdinfo and fill_link_info will print/fill the target_name. Each targets can register show_fdinfo and fill_link_info callbacks to print/fill more target specific information. For example, the below is a fdinfo result for a bpf task iterator. $ cat /proc/1749/fdinfo/7 pos: 0 flags: 02000000 mnt_id: 14 link_type: iter link_id: 11 prog_tag: 990e1f8152f7e54f prog_id: 59 target_name: task Signed-off-by: Yonghong Song <yhs@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20200821184418.574122-1-yhs@fb.com
This commit is contained in:
parent
149cb33955
commit
6b0a249a30
@ -1218,12 +1218,18 @@ typedef int (*bpf_iter_attach_target_t)(struct bpf_prog *prog,
|
|||||||
union bpf_iter_link_info *linfo,
|
union bpf_iter_link_info *linfo,
|
||||||
struct bpf_iter_aux_info *aux);
|
struct bpf_iter_aux_info *aux);
|
||||||
typedef void (*bpf_iter_detach_target_t)(struct bpf_iter_aux_info *aux);
|
typedef void (*bpf_iter_detach_target_t)(struct bpf_iter_aux_info *aux);
|
||||||
|
typedef void (*bpf_iter_show_fdinfo_t) (const struct bpf_iter_aux_info *aux,
|
||||||
|
struct seq_file *seq);
|
||||||
|
typedef int (*bpf_iter_fill_link_info_t)(const struct bpf_iter_aux_info *aux,
|
||||||
|
struct bpf_link_info *info);
|
||||||
|
|
||||||
#define BPF_ITER_CTX_ARG_MAX 2
|
#define BPF_ITER_CTX_ARG_MAX 2
|
||||||
struct bpf_iter_reg {
|
struct bpf_iter_reg {
|
||||||
const char *target;
|
const char *target;
|
||||||
bpf_iter_attach_target_t attach_target;
|
bpf_iter_attach_target_t attach_target;
|
||||||
bpf_iter_detach_target_t detach_target;
|
bpf_iter_detach_target_t detach_target;
|
||||||
|
bpf_iter_show_fdinfo_t show_fdinfo;
|
||||||
|
bpf_iter_fill_link_info_t fill_link_info;
|
||||||
u32 ctx_arg_info_size;
|
u32 ctx_arg_info_size;
|
||||||
struct bpf_ctx_arg_aux ctx_arg_info[BPF_ITER_CTX_ARG_MAX];
|
struct bpf_ctx_arg_aux ctx_arg_info[BPF_ITER_CTX_ARG_MAX];
|
||||||
const struct bpf_iter_seq_info *seq_info;
|
const struct bpf_iter_seq_info *seq_info;
|
||||||
|
@ -4071,6 +4071,13 @@ struct bpf_link_info {
|
|||||||
__u64 cgroup_id;
|
__u64 cgroup_id;
|
||||||
__u32 attach_type;
|
__u32 attach_type;
|
||||||
} cgroup;
|
} cgroup;
|
||||||
|
struct {
|
||||||
|
__aligned_u64 target_name; /* in/out: target_name buffer ptr */
|
||||||
|
__u32 target_name_len; /* in/out: target_name buffer len */
|
||||||
|
union {
|
||||||
|
__u32 map_id;
|
||||||
|
} map;
|
||||||
|
} iter;
|
||||||
struct {
|
struct {
|
||||||
__u32 netns_ino;
|
__u32 netns_ino;
|
||||||
__u32 attach_type;
|
__u32 attach_type;
|
||||||
|
@ -377,10 +377,68 @@ out_unlock:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bpf_iter_link_show_fdinfo(const struct bpf_link *link,
|
||||||
|
struct seq_file *seq)
|
||||||
|
{
|
||||||
|
struct bpf_iter_link *iter_link =
|
||||||
|
container_of(link, struct bpf_iter_link, link);
|
||||||
|
bpf_iter_show_fdinfo_t show_fdinfo;
|
||||||
|
|
||||||
|
seq_printf(seq,
|
||||||
|
"target_name:\t%s\n",
|
||||||
|
iter_link->tinfo->reg_info->target);
|
||||||
|
|
||||||
|
show_fdinfo = iter_link->tinfo->reg_info->show_fdinfo;
|
||||||
|
if (show_fdinfo)
|
||||||
|
show_fdinfo(&iter_link->aux, seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bpf_iter_link_fill_link_info(const struct bpf_link *link,
|
||||||
|
struct bpf_link_info *info)
|
||||||
|
{
|
||||||
|
struct bpf_iter_link *iter_link =
|
||||||
|
container_of(link, struct bpf_iter_link, link);
|
||||||
|
char __user *ubuf = u64_to_user_ptr(info->iter.target_name);
|
||||||
|
bpf_iter_fill_link_info_t fill_link_info;
|
||||||
|
u32 ulen = info->iter.target_name_len;
|
||||||
|
const char *target_name;
|
||||||
|
u32 target_len;
|
||||||
|
|
||||||
|
if (!ulen ^ !ubuf)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
target_name = iter_link->tinfo->reg_info->target;
|
||||||
|
target_len = strlen(target_name);
|
||||||
|
info->iter.target_name_len = target_len + 1;
|
||||||
|
|
||||||
|
if (ubuf) {
|
||||||
|
if (ulen >= target_len + 1) {
|
||||||
|
if (copy_to_user(ubuf, target_name, target_len + 1))
|
||||||
|
return -EFAULT;
|
||||||
|
} else {
|
||||||
|
char zero = '\0';
|
||||||
|
|
||||||
|
if (copy_to_user(ubuf, target_name, ulen - 1))
|
||||||
|
return -EFAULT;
|
||||||
|
if (put_user(zero, ubuf + ulen - 1))
|
||||||
|
return -EFAULT;
|
||||||
|
return -ENOSPC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fill_link_info = iter_link->tinfo->reg_info->fill_link_info;
|
||||||
|
if (fill_link_info)
|
||||||
|
return fill_link_info(&iter_link->aux, info);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct bpf_link_ops bpf_iter_link_lops = {
|
static const struct bpf_link_ops bpf_iter_link_lops = {
|
||||||
.release = bpf_iter_link_release,
|
.release = bpf_iter_link_release,
|
||||||
.dealloc = bpf_iter_link_dealloc,
|
.dealloc = bpf_iter_link_dealloc,
|
||||||
.update_prog = bpf_iter_link_replace,
|
.update_prog = bpf_iter_link_replace,
|
||||||
|
.show_fdinfo = bpf_iter_link_show_fdinfo,
|
||||||
|
.fill_link_info = bpf_iter_link_fill_link_info,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool bpf_link_is_iter(struct bpf_link *link)
|
bool bpf_link_is_iter(struct bpf_link *link)
|
||||||
|
@ -4071,6 +4071,13 @@ struct bpf_link_info {
|
|||||||
__u64 cgroup_id;
|
__u64 cgroup_id;
|
||||||
__u32 attach_type;
|
__u32 attach_type;
|
||||||
} cgroup;
|
} cgroup;
|
||||||
|
struct {
|
||||||
|
__aligned_u64 target_name; /* in/out: target_name buffer ptr */
|
||||||
|
__u32 target_name_len; /* in/out: target_name buffer len */
|
||||||
|
union {
|
||||||
|
__u32 map_id;
|
||||||
|
} map;
|
||||||
|
} iter;
|
||||||
struct {
|
struct {
|
||||||
__u32 netns_ino;
|
__u32 netns_ino;
|
||||||
__u32 attach_type;
|
__u32 attach_type;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user