]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
vsock/test: fix MSG_PEEK handling in recv_buf()
authorLuigi Leonardi <leonardi@redhat.com>
Wed, 15 Apr 2026 15:09:29 +0000 (17:09 +0200)
committerJakub Kicinski <kuba@kernel.org>
Fri, 17 Apr 2026 02:34:22 +0000 (19:34 -0700)
`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>
tools/testing/vsock/util.c
tools/testing/vsock/vsock_test.c

index 1fe1338c79cd15047e34de9ad2fed0ee1778249e..fe316b02a5905834171182ea4ae5eca8f5487f6a 100644 (file)
@@ -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();
index 5bd20ccd9335caafe68e8b7a5d02a4deb3d2deec..bdb0754965df13f8ee90d63dd9dbd686bb18c200 100644 (file)
@@ -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.