[Devel] [PATCH vz10 v2] selftests/uevent: do not fail on a netlink receive buffer overrun

Konstantin Khorenko khorenko at virtuozzo.com
Wed Aug 26 19:49:36 MSK 2026


a kind ping

--
Best regards,

Konstantin Khorenko,
Virtuozzo Linux Kernel Team

On 8/24/26 15:09, Konstantin Khorenko wrote:
> SO_RCVBUF is set to __UEVENT_BUFFER_SIZE, 4KB, which a busy machine
> overruns while the test is listening:
> 
>   No buffer space available - Failed to receive uevent
> 
> Two things are wrong here.
> 
> The socket queue is sized after a single message, while do_test()
> deliberately triggers ten uevents "to account for the case where the
> kernel might drop some", so the queue has to hold more than one.
> 
> Give it its own size and leave the message buffer alone: the kernel caps
> a single uevent at UEVENT_BUFFER_SIZE, 2048 bytes, so 4KB per message is
> already generous.
> 
> The receive loop then treats every error as fatal, ENOBUFS included,
> which defeats those ten uevents. Netlink clears the error after
> reporting it once, so the copies still queued, or still on their way,
> are perfectly receivable. Retry instead.
> 
> do_test() bounds the listener with a two second sigtimedwait(), so a
> retry cannot hang the test.
> 
> https://virtuozzo.atlassian.net/browse/VSTOR-139674
> Feature: fix selftests
> Reported-by: Eva Kurchatova <eva.kurchatova at virtuozzo.com>
> Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
> ---
> Changes in v2:
> - keep __UEVENT_BUFFER_SIZE at 4KB and give SO_RCVBUF its own
>   __UEVENT_RCVBUF_SIZE.  v1 raised the shared macro, which sized the
>   socket queue correctly but also turned the per message buffer into a
>   128KB zero initialized array on the stack, while the kernel caps a
>   single uevent at UEVENT_BUFFER_SIZE, 2048 bytes.
> - retry recvmsg() on ENOBUFS instead of failing.  v1 only made the
>   overrun less likely; the test still died on the first one, even
>   though do_test() triggers ten uevents precisely so that drops are
>   tolerated.
> - subject and commit message updated accordingly.
> 
>  tools/testing/selftests/uevent/uevent_filtering.c | 13 ++++++++++++-
>  1 file changed, 12 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/testing/selftests/uevent/uevent_filtering.c b/tools/testing/selftests/uevent/uevent_filtering.c
> index 8062804ff759..735eb8138c44 100644
> --- a/tools/testing/selftests/uevent/uevent_filtering.c
> +++ b/tools/testing/selftests/uevent/uevent_filtering.c
> @@ -23,6 +23,11 @@
>  
>  #define __DEV_FULL "/sys/devices/virtual/mem/full/uevent"
>  #define __UEVENT_BUFFER_SIZE (2048 * 2)
> +/*
> + * The socket queue has to hold more than a single message: the test
> + * triggers ten uevents and a busy machine overruns a small buffer.
> + */
> +#define __UEVENT_RCVBUF_SIZE (2048 * 64)
>  #define __UEVENT_HEADER "add@/devices/virtual/mem/full"
>  #define __UEVENT_HEADER_LEN sizeof("add@/devices/virtual/mem/full")
>  #define __UEVENT_LISTEN_ALL -1
> @@ -78,7 +83,7 @@ static int uevent_listener(unsigned long post_flags, bool expect_uevent,
>  {
>  	int sk_fd, ret;
>  	socklen_t sk_addr_len;
> -	int rcv_buf_sz = __UEVENT_BUFFER_SIZE;
> +	int rcv_buf_sz = __UEVENT_RCVBUF_SIZE;
>  	uint64_t sync_add = 1;
>  	struct sockaddr_nl sk_addr = { 0 }, rcv_addr = { 0 };
>  	char buf[__UEVENT_BUFFER_SIZE] = { 0 };
> @@ -158,6 +163,12 @@ static int uevent_listener(unsigned long post_flags, bool expect_uevent,
>  		ssize_t r;
>  
>  		r = recvmsg(sk_fd, &hdr, 0);
> +		/*
> +		 * The queue overran.  The kernel clears the error after
> +		 * reporting it once and more uevents are on their way.
> +		 */
> +		if (r < 0 && errno == ENOBUFS)
> +			continue;
>  		if (r <= 0) {
>  			fprintf(stderr, "%s - Failed to receive uevent\n", strerror(errno));
>  			ret = -1;



More information about the Devel mailing list