@@ -34,7 +34,7 @@ struct ring {
3434
3535struct ring_buffer {
3636 struct epoll_event * events ;
37- struct ring * rings ;
37+ struct ring * * rings ;
3838 size_t page_size ;
3939 int epoll_fd ;
4040 int ring_cnt ;
@@ -57,7 +57,7 @@ struct ringbuf_hdr {
5757 __u32 pad ;
5858};
5959
60- static void ringbuf_unmap_ring (struct ring_buffer * rb , struct ring * r )
60+ static void ringbuf_free_ring (struct ring_buffer * rb , struct ring * r )
6161{
6262 if (r -> consumer_pos ) {
6363 munmap (r -> consumer_pos , rb -> page_size );
@@ -67,6 +67,8 @@ static void ringbuf_unmap_ring(struct ring_buffer *rb, struct ring *r)
6767 munmap (r -> producer_pos , rb -> page_size + 2 * (r -> mask + 1 ));
6868 r -> producer_pos = NULL ;
6969 }
70+
71+ free (r );
7072}
7173
7274/* Add extra RINGBUF maps to this ring buffer manager */
@@ -107,8 +109,10 @@ int ring_buffer__add(struct ring_buffer *rb, int map_fd,
107109 return libbpf_err (- ENOMEM );
108110 rb -> events = tmp ;
109111
110- r = & rb -> rings [rb -> ring_cnt ];
111- memset (r , 0 , sizeof (* r ));
112+ r = calloc (1 , sizeof (* r ));
113+ if (!r )
114+ return libbpf_err (- ENOMEM );
115+ rb -> rings [rb -> ring_cnt ] = r ;
112116
113117 r -> map_fd = map_fd ;
114118 r -> sample_cb = sample_cb ;
@@ -121,7 +125,7 @@ int ring_buffer__add(struct ring_buffer *rb, int map_fd,
121125 err = - errno ;
122126 pr_warn ("ringbuf: failed to mmap consumer page for map fd=%d: %d\n" ,
123127 map_fd , err );
124- return libbpf_err ( err ) ;
128+ goto err_out ;
125129 }
126130 r -> consumer_pos = tmp ;
127131
@@ -131,16 +135,16 @@ int ring_buffer__add(struct ring_buffer *rb, int map_fd,
131135 */
132136 mmap_sz = rb -> page_size + 2 * (__u64 )info .max_entries ;
133137 if (mmap_sz != (__u64 )(size_t )mmap_sz ) {
138+ err = - E2BIG ;
134139 pr_warn ("ringbuf: ring buffer size (%u) is too big\n" , info .max_entries );
135- return libbpf_err ( - E2BIG ) ;
140+ goto err_out ;
136141 }
137142 tmp = mmap (NULL , (size_t )mmap_sz , PROT_READ , MAP_SHARED , map_fd , rb -> page_size );
138143 if (tmp == MAP_FAILED ) {
139144 err = - errno ;
140- ringbuf_unmap_ring (rb , r );
141145 pr_warn ("ringbuf: failed to mmap data pages for map fd=%d: %d\n" ,
142146 map_fd , err );
143- return libbpf_err ( err ) ;
147+ goto err_out ;
144148 }
145149 r -> producer_pos = tmp ;
146150 r -> data = tmp + rb -> page_size ;
@@ -152,14 +156,17 @@ int ring_buffer__add(struct ring_buffer *rb, int map_fd,
152156 e -> data .fd = rb -> ring_cnt ;
153157 if (epoll_ctl (rb -> epoll_fd , EPOLL_CTL_ADD , map_fd , e ) < 0 ) {
154158 err = - errno ;
155- ringbuf_unmap_ring (rb , r );
156159 pr_warn ("ringbuf: failed to epoll add map fd=%d: %d\n" ,
157160 map_fd , err );
158- return libbpf_err ( err ) ;
161+ goto err_out ;
159162 }
160163
161164 rb -> ring_cnt ++ ;
162165 return 0 ;
166+
167+ err_out :
168+ ringbuf_free_ring (rb , r );
169+ return libbpf_err (err );
163170}
164171
165172void ring_buffer__free (struct ring_buffer * rb )
@@ -170,7 +177,7 @@ void ring_buffer__free(struct ring_buffer *rb)
170177 return ;
171178
172179 for (i = 0 ; i < rb -> ring_cnt ; ++ i )
173- ringbuf_unmap_ring (rb , & rb -> rings [i ]);
180+ ringbuf_free_ring (rb , rb -> rings [i ]);
174181 if (rb -> epoll_fd >= 0 )
175182 close (rb -> epoll_fd );
176183
@@ -278,7 +285,7 @@ int ring_buffer__consume(struct ring_buffer *rb)
278285 int i ;
279286
280287 for (i = 0 ; i < rb -> ring_cnt ; i ++ ) {
281- struct ring * ring = & rb -> rings [i ];
288+ struct ring * ring = rb -> rings [i ];
282289
283290 err = ringbuf_process_ring (ring );
284291 if (err < 0 )
@@ -305,7 +312,7 @@ int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms)
305312
306313 for (i = 0 ; i < cnt ; i ++ ) {
307314 __u32 ring_id = rb -> events [i ].data .fd ;
308- struct ring * ring = & rb -> rings [ring_id ];
315+ struct ring * ring = rb -> rings [ring_id ];
309316
310317 err = ringbuf_process_ring (ring );
311318 if (err < 0 )
@@ -323,6 +330,58 @@ int ring_buffer__epoll_fd(const struct ring_buffer *rb)
323330 return rb -> epoll_fd ;
324331}
325332
333+ struct ring * ring_buffer__ring (struct ring_buffer * rb , unsigned int idx )
334+ {
335+ if (idx >= rb -> ring_cnt )
336+ return errno = ERANGE , NULL ;
337+
338+ return rb -> rings [idx ];
339+ }
340+
341+ unsigned long ring__consumer_pos (const struct ring * r )
342+ {
343+ /* Synchronizes with smp_store_release() in ringbuf_process_ring(). */
344+ return smp_load_acquire (r -> consumer_pos );
345+ }
346+
347+ unsigned long ring__producer_pos (const struct ring * r )
348+ {
349+ /* Synchronizes with smp_store_release() in __bpf_ringbuf_reserve() in
350+ * the kernel.
351+ */
352+ return smp_load_acquire (r -> producer_pos );
353+ }
354+
355+ size_t ring__avail_data_size (const struct ring * r )
356+ {
357+ unsigned long cons_pos , prod_pos ;
358+
359+ cons_pos = ring__consumer_pos (r );
360+ prod_pos = ring__producer_pos (r );
361+ return prod_pos - cons_pos ;
362+ }
363+
364+ size_t ring__size (const struct ring * r )
365+ {
366+ return r -> mask + 1 ;
367+ }
368+
369+ int ring__map_fd (const struct ring * r )
370+ {
371+ return r -> map_fd ;
372+ }
373+
374+ int ring__consume (struct ring * r )
375+ {
376+ int64_t res ;
377+
378+ res = ringbuf_process_ring (r );
379+ if (res < 0 )
380+ return libbpf_err (res );
381+
382+ return res > INT_MAX ? INT_MAX : res ;
383+ }
384+
326385static void user_ringbuf_unmap_ring (struct user_ring_buffer * rb )
327386{
328387 if (rb -> consumer_pos ) {
0 commit comments