From: Luigi Leonardi Date: Wed, 15 Apr 2026 15:09:29 +0000 (+0200) Subject: vsock/test: fix MSG_PEEK handling in recv_buf() X-Git-Tag: v7.1-rc1~36^2~62^2~1 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=a3f77afbf67d5ddbc8938fd5627a11221d8a3368;p=thirdparty%2Flinux.git vsock/test: fix MSG_PEEK handling in recv_buf() `recv_buf` does not handle the MSG_PEEK flag correctly: it keeps calling `recv` until all requested bytes are available or an error occurs. The problem is how it calculates the number of bytes read: MSG_PEEK doesn't consume any bytes and will re-read the same bytes from the buffer head, so summing the return value every time is wrong. Moreover, MSG_PEEK doesn't consume the bytes in the buffer, so if more bytes are requested than are available, the loop will never terminate, because `recv` will never return EOF. For this reason, we need to compare the number of bytes read with the number of bytes expected. Add a check: if the MSG_PEEK flag is present, update the byte counter and break out of the loop only after at least the expected number of bytes have been received; otherwise, retry after a short delay to avoid consuming too many CPU cycles. This allows us to simplify the `test_stream_credit_update_test` by reusing `recv_buf`, like some other tests already do. Suggested-by: Stefano Garzarella Signed-off-by: Luigi Leonardi Reviewed-by: Stefano Garzarella Link: https://patch.msgid.link/20260415-fix_peek-v4-2-8207e872759e@redhat.com Signed-off-by: Jakub Kicinski --- diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c index 1fe1338c79cd..fe316b02a590 100644 --- a/tools/testing/vsock/util.c +++ b/tools/testing/vsock/util.c @@ -381,7 +381,13 @@ void send_buf(int fd, const void *buf, size_t len, int flags, } } +#define RECV_PEEK_RETRY_USEC (10 * 1000) + /* Receive bytes in a buffer and check the return value. + * + * When MSG_PEEK is set, recv() is retried until it returns at least + * expected_ret bytes. The function returns on error, EOF, or timeout + * as usual. * * expected_ret: * <0 Negative errno (for testing errors) @@ -403,6 +409,15 @@ void recv_buf(int fd, void *buf, size_t len, int flags, ssize_t expected_ret) if (ret <= 0) break; + if (flags & MSG_PEEK) { + if (ret >= expected_ret) { + nread = ret; + break; + } + timeout_usleep(RECV_PEEK_RETRY_USEC); + continue; + } + nread += ret; } while (nread < len); timeout_end(); diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c index 5bd20ccd9335..bdb0754965df 100644 --- a/tools/testing/vsock/vsock_test.c +++ b/tools/testing/vsock/vsock_test.c @@ -1500,18 +1500,7 @@ static void test_stream_credit_update_test(const struct test_opts *opts, } /* Wait until there will be 128KB of data in rx queue. */ - while (1) { - ssize_t res; - - res = recv(fd, buf, buf_size, MSG_PEEK); - if (res == buf_size) - break; - - if (res <= 0) { - fprintf(stderr, "unexpected 'recv()' return: %zi\n", res); - exit(EXIT_FAILURE); - } - } + recv_buf(fd, buf, buf_size, MSG_PEEK, buf_size); /* There is 128KB of data in the socket's rx queue, dequeue first * 64KB, credit update is sent if 'low_rx_bytes_test' == true.