[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20171025113249.3283aebc@redhat.com>
Date: Wed, 25 Oct 2017 11:32:49 +0200
From: Jesper Dangaard Brouer <brouer@...hat.com>
To: Yonghong Song <yhs@...com>
Cc: brouer@...hat.com, <peterz@...radead.org>, <rostedt@...dmis.org>,
<ast@...com>, <daniel@...earbox.net>, <kafai@...com>,
<netdev@...r.kernel.org>, <kernel-team@...com>
Subject: Re: [PATCH net-next v3 2/3] bpf: permit multiple bpf attachments
for a single perf event
On Mon, 23 Oct 2017 23:53:08 -0700 Yonghong Song <yhs@...com> wrote:
> This patch enables multiple bpf attachments for a
> kprobe/uprobe/tracepoint single trace event.
Thanks for working on this, I've hit this issue, where another program
BPF-attach to a tracepoint, and the existing userspace-side prog
doesn't notice. (Specifically in samples/bpf/xdp_monitor_user.c)
Should my issue be gone now?
> Each trace_event keeps a list of attached perf events.
> When an event happens, all attached bpf programs will
> be executed based on the order of attachment.
Can I somehow view/list the attached bpf programs from userspace?
[...]
You didn't describe the expected semantics of bpf-programs return codes.
>From below code it looks like, that if single program in the list/array
returns 0 then the collective return code is also 0 (is that correct?).
Where 0 means don't store the event into the perf record ring-buffer.
Is this a good semantics?
I do use the return 0 trick to save cycles (in samples/bpf/xdp_monitor_kern.c).
But when someone attach a new tracepoint, e.g. via perf record -e, then
they might be surprised that they don't receive any events, when my
xdp_monitor happen to be running at the same time...?
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index 1e334b2..172be7f 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -273,18 +273,38 @@ int bpf_prog_array_length(struct bpf_prog_array __rcu *progs);
> int bpf_prog_array_copy_to_user(struct bpf_prog_array __rcu *progs,
> __u32 __user *prog_ids, u32 cnt);
>
> -#define BPF_PROG_RUN_ARRAY(array, ctx, func) \
> +void bpf_prog_array_delete_safe(struct bpf_prog_array __rcu *progs,
> + struct bpf_prog *old_prog);
> +int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array,
> + struct bpf_prog *exclude_prog,
> + struct bpf_prog *include_prog,
> + struct bpf_prog_array **new_array);
> +
> +#define __BPF_PROG_RUN_ARRAY(array, ctx, func, check_non_null) \
> ({ \
> - struct bpf_prog **_prog; \
> + struct bpf_prog **_prog, *__prog; \
> + struct bpf_prog_array *_array; \
> u32 _ret = 1; \
> rcu_read_lock(); \
> - _prog = rcu_dereference(array)->progs; \
> - for (; *_prog; _prog++) \
> - _ret &= func(*_prog, ctx); \
> + _array = rcu_dereference(array); \
> + if (unlikely(check_non_null && !_array))\
> + goto _out; \
> + _prog = _array->progs; \
> + while ((__prog = READ_ONCE(*_prog))) { \
> + _ret &= func(__prog, ctx); \
> + _prog++; \
> + } \
> +_out: \
> rcu_read_unlock(); \
> _ret; \
> })
>
> +#define BPF_PROG_RUN_ARRAY(array, ctx, func) \
> + __BPF_PROG_RUN_ARRAY(array, ctx, func, false)
> +
> +#define BPF_PROG_RUN_ARRAY_CHECK(array, ctx, func) \
> + __BPF_PROG_RUN_ARRAY(array, ctx, func, true)
> +
> #ifdef CONFIG_BPF_SYSCALL
> DECLARE_PER_CPU(int, bpf_prog_active);
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Principal Kernel Engineer at Red Hat
LinkedIn: http://www.linkedin.com/in/brouer
Powered by blists - more mailing lists