Skip to content

Commit 50408d7

Browse files
committed
Merge branch 'libbpf-api-to-partially-consume-items-from-ringbuffer'
Andrea Righi says: ==================== libbpf: API to partially consume items from ringbuffer Introduce ring__consume_n() and ring_buffer__consume_n() API to partially consume items from one (or more) ringbuffer(s). This can be useful, for example, to consume just a single item or when we need to copy multiple items to a limited user-space buffer from the ringbuffer callback. Practical example (where this API can be used): https://github.com/sched-ext/scx/blob/b7c06b9ed9f72cad83c31e39e9c4e2cfd8683a55/rust/scx_rustland_core/src/bpf.rs#L217 See also: https://lore.kernel.org/lkml/[email protected]/T/#u v4: - open a new 1.5.0 cycle v3: - rename ring__consume_max() -> ring__consume_n() and ring_buffer__consume_max() -> ring_buffer__consume_n() - add new API to a new 1.5.0 cycle - fixed minor nits / comments v2: - introduce a new API instead of changing the callback's retcode behavior ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Andrii Nakryiko <[email protected]>
2 parents d564ffd + 4d22ea9 commit 50408d7

File tree

4 files changed

+65
-10
lines changed

4 files changed

+65
-10
lines changed

tools/lib/bpf/libbpf.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,6 +1293,7 @@ LIBBPF_API int ring_buffer__add(struct ring_buffer *rb, int map_fd,
12931293
ring_buffer_sample_fn sample_cb, void *ctx);
12941294
LIBBPF_API int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms);
12951295
LIBBPF_API int ring_buffer__consume(struct ring_buffer *rb);
1296+
LIBBPF_API int ring_buffer__consume_n(struct ring_buffer *rb, size_t n);
12961297
LIBBPF_API int ring_buffer__epoll_fd(const struct ring_buffer *rb);
12971298

12981299
/**
@@ -1367,6 +1368,17 @@ LIBBPF_API int ring__map_fd(const struct ring *r);
13671368
*/
13681369
LIBBPF_API int ring__consume(struct ring *r);
13691370

1371+
/**
1372+
* @brief **ring__consume_n()** consumes up to a requested amount of items from
1373+
* a ringbuffer without event polling.
1374+
*
1375+
* @param r A ringbuffer object.
1376+
* @param n Maximum amount of items to consume.
1377+
* @return The number of items consumed, or a negative number if any of the
1378+
* callbacks return an error.
1379+
*/
1380+
LIBBPF_API int ring__consume_n(struct ring *r, size_t n);
1381+
13701382
struct user_ring_buffer_opts {
13711383
size_t sz; /* size of this struct, for forward/backward compatibility */
13721384
};

tools/lib/bpf/libbpf.map

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,3 +416,9 @@ LIBBPF_1.4.0 {
416416
btf__new_split;
417417
btf_ext__raw_data;
418418
} LIBBPF_1.3.0;
419+
420+
LIBBPF_1.5.0 {
421+
global:
422+
ring__consume_n;
423+
ring_buffer__consume_n;
424+
} LIBBPF_1.4.0;

tools/lib/bpf/libbpf_version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
#define __LIBBPF_VERSION_H
55

66
#define LIBBPF_MAJOR_VERSION 1
7-
#define LIBBPF_MINOR_VERSION 4
7+
#define LIBBPF_MINOR_VERSION 5
88

99
#endif /* __LIBBPF_VERSION_H */

tools/lib/bpf/ringbuf.c

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ static inline int roundup_len(__u32 len)
231231
return (len + 7) / 8 * 8;
232232
}
233233

234-
static int64_t ringbuf_process_ring(struct ring *r)
234+
static int64_t ringbuf_process_ring(struct ring *r, size_t n)
235235
{
236236
int *len_ptr, len, err;
237237
/* 64-bit to avoid overflow in case of extreme application behavior */
@@ -268,12 +268,42 @@ static int64_t ringbuf_process_ring(struct ring *r)
268268
}
269269

270270
smp_store_release(r->consumer_pos, cons_pos);
271+
272+
if (cnt >= n)
273+
goto done;
271274
}
272275
} while (got_new_data);
273276
done:
274277
return cnt;
275278
}
276279

280+
/* Consume available ring buffer(s) data without event polling, up to n
281+
* records.
282+
*
283+
* Returns number of records consumed across all registered ring buffers (or
284+
* n, whichever is less), or negative number if any of the callbacks return
285+
* error.
286+
*/
287+
int ring_buffer__consume_n(struct ring_buffer *rb, size_t n)
288+
{
289+
int64_t err, res = 0;
290+
int i;
291+
292+
for (i = 0; i < rb->ring_cnt; i++) {
293+
struct ring *ring = rb->rings[i];
294+
295+
err = ringbuf_process_ring(ring, n);
296+
if (err < 0)
297+
return libbpf_err(err);
298+
res += err;
299+
n -= err;
300+
301+
if (n == 0)
302+
break;
303+
}
304+
return res;
305+
}
306+
277307
/* Consume available ring buffer(s) data without event polling.
278308
* Returns number of records consumed across all registered ring buffers (or
279309
* INT_MAX, whichever is less), or negative number if any of the callbacks
@@ -287,13 +317,15 @@ int ring_buffer__consume(struct ring_buffer *rb)
287317
for (i = 0; i < rb->ring_cnt; i++) {
288318
struct ring *ring = rb->rings[i];
289319

290-
err = ringbuf_process_ring(ring);
320+
err = ringbuf_process_ring(ring, INT_MAX);
291321
if (err < 0)
292322
return libbpf_err(err);
293323
res += err;
324+
if (res > INT_MAX) {
325+
res = INT_MAX;
326+
break;
327+
}
294328
}
295-
if (res > INT_MAX)
296-
return INT_MAX;
297329
return res;
298330
}
299331

@@ -314,13 +346,13 @@ int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms)
314346
__u32 ring_id = rb->events[i].data.fd;
315347
struct ring *ring = rb->rings[ring_id];
316348

317-
err = ringbuf_process_ring(ring);
349+
err = ringbuf_process_ring(ring, INT_MAX);
318350
if (err < 0)
319351
return libbpf_err(err);
320352
res += err;
321353
}
322354
if (res > INT_MAX)
323-
return INT_MAX;
355+
res = INT_MAX;
324356
return res;
325357
}
326358

@@ -371,17 +403,22 @@ int ring__map_fd(const struct ring *r)
371403
return r->map_fd;
372404
}
373405

374-
int ring__consume(struct ring *r)
406+
int ring__consume_n(struct ring *r, size_t n)
375407
{
376-
int64_t res;
408+
int res;
377409

378-
res = ringbuf_process_ring(r);
410+
res = ringbuf_process_ring(r, n);
379411
if (res < 0)
380412
return libbpf_err(res);
381413

382414
return res > INT_MAX ? INT_MAX : res;
383415
}
384416

417+
int ring__consume(struct ring *r)
418+
{
419+
return ring__consume_n(r, INT_MAX);
420+
}
421+
385422
static void user_ringbuf_unmap_ring(struct user_ring_buffer *rb)
386423
{
387424
if (rb->consumer_pos) {

0 commit comments

Comments
 (0)