mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 03:11:11 -04:00
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 <sgarzare@redhat.com> Signed-off-by: Luigi Leonardi <leonardi@redhat.com> Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> Link: https://patch.msgid.link/20260415-fix_peek-v4-2-8207e872759e@redhat.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
080f22f5d3
commit
a3f77afbf6
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user