ringbuf_process_ring() checks the record bound only after advancing the
consumer position and invoking the callback. A zero bound therefore
consumes the first available record.

Return before reading the ring positions when the bound is zero so
ring_buffer__consume_n() and ring__consume_n() leave all records queued.

Fixes: 4d22ea94ea33 ("libbpf: Add ring__consume_n / ring_buffer__consume_n")
Assisted-by: Codex:gpt-5.5
Signed-off-by: Tamir Duberstein <[email protected]>
---
 tools/lib/bpf/ringbuf.c                          |  3 +++
 tools/testing/selftests/bpf/prog_tests/ringbuf.c | 13 +++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/tools/lib/bpf/ringbuf.c b/tools/lib/bpf/ringbuf.c
index 00ec4837a06d..f2bb619d5a75 100644
--- a/tools/lib/bpf/ringbuf.c
+++ b/tools/lib/bpf/ringbuf.c
@@ -240,6 +240,9 @@ static int64_t ringbuf_process_ring(struct ring *r, size_t 
n)
        bool got_new_data;
        void *sample;
 
+       if (n == 0)
+               return 0;
+
        cons_pos = smp_load_acquire(r->consumer_pos);
        do {
                got_new_data = false;
diff --git a/tools/testing/selftests/bpf/prog_tests/ringbuf.c 
b/tools/testing/selftests/bpf/prog_tests/ringbuf.c
index 64520684d2cb..4f0558f14847 100644
--- a/tools/testing/selftests/bpf/prog_tests/ringbuf.c
+++ b/tools/testing/selftests/bpf/prog_tests/ringbuf.c
@@ -404,6 +404,7 @@ static int process_n_sample(void *ctx, void *data, size_t 
len)
 static void ringbuf_n_subtest(void)
 {
        struct test_ringbuf_n_lskel *skel_n;
+       struct ring *ring;
        int err, i;
 
        skel_n = test_ringbuf_n_lskel__open();
@@ -431,6 +432,18 @@ static void ringbuf_n_subtest(void)
        for (i = 0; i < N_TOT_SAMPLES; i++)
                syscall(__NR_getpgid);
 
+       ring = ring_buffer__ring(ringbuf, 0);
+       if (!ASSERT_OK_PTR(ring, "ring_buffer__ring"))
+               goto cleanup_ringbuf;
+
+       err = ring_buffer__consume_n(ringbuf, 0);
+       if (!ASSERT_EQ(err, 0, "ringbuf_consume_zero"))
+               goto cleanup_ringbuf;
+
+       err = ring__consume_n(ring, 0);
+       if (!ASSERT_EQ(err, 0, "ring_consume_zero"))
+               goto cleanup_ringbuf;
+
        /* Consume all samples from the ring buffer in batches of N_SAMPLES */
        for (i = 0; i < N_TOT_SAMPLES; i += err) {
                err = ring_buffer__consume_n(ringbuf, N_SAMPLES);

-- 
2.55.0.rc0.96.gc050c23164


Reply via email to