Re: Re: Re: [PATCH bpf-next 1/2] libbpf: add ring_buffer__query

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

 



On 9/12/23 17:23, Andrii Nakryiko wrote:
Second, this `unsigned int index` is not a good interface. There is
nothing in ring_buffer APIs that operates based on such an index.
The index is the heart of the problem, and I expected there might be
concerns about it. The issue is that right now, only struct ring_buffer
is exposed to the user, but this struct actually contains many
ringbuffers, with no API for referencing any particular ringbuffer.

One thing we could do is expose struct ring * as an opaque type:

struct ring *ring_buffer__get(struct ring_buffer *rb, unsigned int index);
__u32 ring_buffer__count(struct ring_buffer *rb);

Then individual ringbuffers could have methods like:

__u64 ring__get_avail_data(struct ring *r);
__u64 ring__get_producer_pos(struct ring *r);
__u64 ring__get_consumer_pos(struct ring *r);

And usermode could do something like this:

for (i = 0; i < ring_buffer__count(rb); i++) {
      struct ring *r = ring_buffer__get(rb);
      avail_data = ring__get_avail_data(r);
      /* do some logic with avail_data */
}

Because struct ring_buffer currently contains many ringbuffers, I think
we need to add an index, either directly in these methods or by exposing
struct ring * as an opaque type.

I appreciate your response; please let me know what you think.

I don't really have a better proposal (I tried). Let's go with
basically what you proposed, let's just follow libbpf naming
convention to not use "get" in getters. Something like this (notice
return types):
The below API looks good to me; I'll work on this.

struct ring *ring_buffer__ring(struct ring_buffer *rb, int idx);

unsigned long ring__producer_pos(const struct ring *r);
unsigned long ring__consumer_pos(const struct ring *r);
/* document that this is racy estimate */
size_t ring__avail_data_size(const struct ring *r);
size_t ring__size(const struct ring *r);
int ring__map_fd(const struct ring *r);

so we have a more-or-less complete set of getters. We can probably
also later add consume() implementation (but not poll!).

Also, we'll need to decide whether returned struct ring * pointers are
invalidated on ring_buffer__add() or not. It probably would be less
error-prone if they were not, and it's easy to implement. Instead of
having `struct ring *rings` inside struct ring_buffer, we can have an
array of pointers and keep struct ring * pointers stable.

I agree with that; this seems like a big foot-gun otherwise, especially as much of the time realloc will expand in-place and therefore nothing will break, so it could easily lead to a "rare crash" type of scenario for users.


BTW, we should probably add producer/consumer pos for
user_ring_buffer, which is much more straightforward API-wise, because
it's always a single ringbuf, so no need to build extra abstractions.




[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