Re: [PATCH] bpf: smp_wmb before bpf_ringbuf really commit

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On 10/31/2024 4:42 PM, zhongjinji@xxxxxxxxx wrote:
> From: zhongjinji <zhongjinji@xxxxxxxxx>
>
> To guarantee visibility of writing ringbuffer,it is necessary
> to call smp_wmb before ringbuffer really commit.
> for instance, when updating the data of buffer in cpu1,
> it is not visible for the cpu2 which may be accessing buffer. This may
> lead to the consumer accessing a incorrect data. using the smp_wmb
> before commmit will guarantee that the consume can access the correct data.
>
> CPU1:
>     struct mem_event_t* data = bpf_ringbuf_reserve();
>     data->type = MEM_EVENT_KSWAPD_WAKE;
>     data->event_data.kswapd_wake.node_id = args->nid;
>     bpf_ringbuf_commit(data);
>
> CPU2:
>     cons_pos = smp_load_acquire(r->consumer_pos);
>     len_ptr = r->data + (cons_pos & r->mask);
>     sample = (void *)len_ptr + BPF_RINGBUF_HDR_SZ;
>     access to sample

It seems you didn't use the ringbuf related APIs (e.g.,
ring_buffer__consume()) in libbpf to access the ring buffer. In my
understanding, the "xchg(&hdr->len, new_len)" in bpf_ringbuf_commit()
works as the barrier to ensure the order of committed data and hdr->len,
and accordingly the "smp_load_acquire(len_ptr)" in
ringbuf_process_ring() in libbpf works as the paired barrier to ensure
the order of hdr->len and the committed data. So I think the extra
smp_wmb() in the kernel is not necessary here. Instead, you should fix
your code in the userspace.
>
> Signed-off-by: zhongjinji <zhongjinji@xxxxxxxxx>
> ---
>  kernel/bpf/ringbuf.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/kernel/bpf/ringbuf.c b/kernel/bpf/ringbuf.c
> index e1cfe890e0be..a66059e2b0d6 100644
> --- a/kernel/bpf/ringbuf.c
> +++ b/kernel/bpf/ringbuf.c
> @@ -508,6 +508,10 @@ static void bpf_ringbuf_commit(void *sample, u64 flags, bool discard)
>  	rec_pos = (void *)hdr - (void *)rb->data;
>  	cons_pos = smp_load_acquire(&rb->consumer_pos) & rb->mask;
>  
> +	/* Make sure the modification of data is visible on other CPU's
> +	 * before consume the event
> +	 */
> +	smp_wmb();
>  	if (flags & BPF_RB_FORCE_WAKEUP)
>  		irq_work_queue(&rb->work);
>  	else if (cons_pos == rec_pos && !(flags & BPF_RB_NO_WAKEUP))





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux