Every existing splice call in this file either passes
SPLICE_F_NONBLOCK or runs on a blocking socket, so nothing
exercises the socket's own O_NONBLOCK on the splice path. A change
that stops consulting sock->file->f_flags puts splice(2) and
sendfile(2) back to sleeping in tls_rx_rec_wait() while a peer
streams empty records, and the suite still reports pass.

Run the zero-length record variants a second time with O_NONBLOCK
set on the socket and SPLICE_F_NONBLOCK left out of the splice
flags. Each variant expects the same result with either flag. A
kernel that ignores the socket flag sleeps in the EAGAIN variant
until the harness timeout rather than returning.

Signed-off-by: Chuck Lever <[email protected]>
---
 tools/testing/selftests/net/tls.c | 38 ++++++++++++++++++++++++++++++++------
 1 file changed, 32 insertions(+), 6 deletions(-)

diff --git a/tools/testing/selftests/net/tls.c 
b/tools/testing/selftests/net/tls.c
index aa66d0bbd1b5..cdd53b8f0ed8 100644
--- a/tools/testing/selftests/net/tls.c
+++ b/tools/testing/selftests/net/tls.c
@@ -2829,7 +2829,11 @@ FIXTURE_TEARDOWN(zero_len_splice)
  * EAGAIN for a run with no payload behind it, and EINVAL for a control
  * record behind the run.
  */
-TEST_F(zero_len_splice, test)
+static void
+zero_len_do_splice(struct __test_metadata *_metadata,
+                  FIXTURE_DATA(zero_len_splice) *self,
+                  const FIXTURE_VARIANT(zero_len_splice) *variant,
+                  unsigned int splice_flags)
 {
        struct pollfd pfd = { .fd = self->cfd, .events = POLLIN };
        const struct raw_rec *payload;
@@ -2837,16 +2841,13 @@ TEST_F(zero_len_splice, test)
        ssize_t ret;
        int p[2];
 
-       if (self->notls)
-               SKIP(return, "no TLS support");
-
        ASSERT_GE(pipe(p), 0);
 
        payload = zero_len_send_recs(_metadata, self->fd, variant->recs);
 
        if (variant->splice_ret < 0) {
                ret = splice(self->cfd, NULL, p[1], NULL, sizeof(buf),
-                            SPLICE_F_NONBLOCK);
+                            splice_flags);
                EXPECT_EQ(ret, -1);
                EXPECT_EQ(errno, -variant->splice_ret);
        } else {
@@ -2854,7 +2855,7 @@ TEST_F(zero_len_splice, test)
                 * below blocks until the harness timeout.
                 */
                ASSERT_EQ(splice(self->cfd, NULL, p[1], NULL, sizeof(buf),
-                                SPLICE_F_NONBLOCK), variant->splice_ret);
+                                splice_flags), variant->splice_ret);
                ret = read(p[0], buf, sizeof(buf));
                EXPECT_EQ(ret, variant->splice_ret);
                if (ret == variant->splice_ret)
@@ -2869,6 +2870,31 @@ TEST_F(zero_len_splice, test)
        close(p[1]);
 }
 
+TEST_F(zero_len_splice, test)
+{
+       if (self->notls)
+               SKIP(return, "no TLS support");
+
+       zero_len_do_splice(_metadata, self, variant, SPLICE_F_NONBLOCK);
+}
+
+/* The socket's O_NONBLOCK governs the record wait, as on a plain TCP
+ * socket, so splice behaves the same with or without SPLICE_F_NONBLOCK.
+ */
+TEST_F(zero_len_splice, nonblock_socket)
+{
+       int sflags;
+
+       if (self->notls)
+               SKIP(return, "no TLS support");
+
+       sflags = fcntl(self->cfd, F_GETFL, 0);
+       ASSERT_GE(sflags, 0);
+       ASSERT_EQ(fcntl(self->cfd, F_SETFL, sflags | O_NONBLOCK), 0);
+
+       zero_len_do_splice(_metadata, self, variant, 0);
+}
+
 FIXTURE(tls_err)
 {
        int fd, cfd;

-- 
2.55.0


Reply via email to