Add tun_ring_unconsume() and tap_ring_unconsume() wrappers to allow external modules (e.g. vhost-net) to return previously consumed entries back to the ring. This complements tun_ring_consume_batched() and tap_ring_consume_batched() and enables proper error handling when consumed packets need to be rolled back. The functions delegate to ptr_ring_unconsume() and take a destroy callback for entries that cannot be returned to the ring. Co-developed-by: Tim Gebauer Signed-off-by: Tim Gebauer Co-developed by: Jon Kohler Signed-off-by: Jon Kohler Signed-off-by: Simon Schippers --- drivers/net/tap.c | 10 ++++++++++ drivers/net/tun.c | 10 ++++++++++ include/linux/if_tap.h | 4 ++++ include/linux/if_tun.h | 5 +++++ 4 files changed, 29 insertions(+) diff --git a/drivers/net/tap.c b/drivers/net/tap.c index 01717c8fd284..0069e2f177f4 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -837,6 +837,16 @@ int tap_ring_consume_batched(struct file *file, void **array, int n) } EXPORT_SYMBOL_GPL(tap_ring_consume_batched); +void tap_ring_unconsume(struct file *file, void **batch, int n, + void (*destroy)(void *)) +{ + struct tap_queue *q = file->private_data; + struct ptr_ring *ring = &q->ring; + + ptr_ring_unconsume(ring, batch, n, destroy); +} +EXPORT_SYMBOL_GPL(tap_ring_unconsume); + static ssize_t tap_do_read(struct tap_queue *q, struct iov_iter *to, int noblock, struct sk_buff *skb) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 42df185341ad..bf109440d2c7 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -3837,6 +3837,16 @@ int tun_ring_consume_batched(struct file *file, void **array, int n) } EXPORT_SYMBOL_GPL(tun_ring_consume_batched); +void tun_ring_unconsume(struct file *file, void **batch, int n, + void (*destroy)(void *)) +{ + struct tun_file *tfile = file->private_data; + struct ptr_ring *ring = &tfile->tx_ring; + + ptr_ring_unconsume(ring, batch, n, destroy); +} +EXPORT_SYMBOL_GPL(tun_ring_unconsume); + struct ptr_ring *tun_get_tx_ring(struct file *file) { struct tun_file *tfile; diff --git a/include/linux/if_tap.h b/include/linux/if_tap.h index cf8b90320b8d..28326a69745a 100644 --- a/include/linux/if_tap.h +++ b/include/linux/if_tap.h @@ -12,6 +12,8 @@ struct socket; struct socket *tap_get_socket(struct file *); struct ptr_ring *tap_get_ptr_ring(struct file *file); int tap_ring_consume_batched(struct file *file, void **array, int n); +void tap_ring_unconsume(struct file *file, void **batch, int n, + void (*destroy)(void *)); #else #include #include @@ -28,6 +30,8 @@ static inline int tap_ring_consume_batched(struct file *f, { return 0; } +static inline void tap_ring_unconsume(struct file *file, void **batch, + int n, void (*destroy)(void *)) {} #endif /* CONFIG_TAP */ /* diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h index 444dda75a372..1274c6b34eb6 100644 --- a/include/linux/if_tun.h +++ b/include/linux/if_tun.h @@ -23,6 +23,8 @@ struct tun_msg_ctl { struct socket *tun_get_socket(struct file *); struct ptr_ring *tun_get_tx_ring(struct file *file); int tun_ring_consume_batched(struct file *file, void **array, int n); +void tun_ring_unconsume(struct file *file, void **batch, int n, + void (*destroy)(void *)); static inline bool tun_is_xdp_frame(void *ptr) { @@ -62,6 +64,9 @@ static inline int tun_ring_consume_batched(struct file *file, return 0; } +static inline void tun_ring_unconsume(struct file *file, void **batch, + int n, void (*destroy)(void *)) {} + static inline bool tun_is_xdp_frame(void *ptr) { return false; -- 2.43.0