From 755436920d78f7a5462aa85a85f9dca661c2afbc Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Wed, 9 Jul 2025 19:05:23 +0200 Subject: [PATCH] MEDIUM: splice: Don't consider EINVAL to be a fatal error Don't consider that EINVAL is a fatal error, when calling splice(). When doing splicing from a kTLS socket, splice() will set errno to EINVAL if the next record to be read is not an application data record. This is not a fatal error, it just means we have to use recvmsg() to read it, and potentially we can then resume using splicing. It is unfortunate that EINVAL was used for that case, but we should never get any other case of receiving EINVAL from splice(), so it should be safe to treat it as non-fatal. --- src/raw_sock.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/raw_sock.c b/src/raw_sock.c index ddfe0e464..5ef904d74 100644 --- a/src/raw_sock.c +++ b/src/raw_sock.c @@ -123,8 +123,20 @@ int raw_sock_to_pipe(struct connection *conn, void *xprt_ctx, struct pipe *pipe, /* splice not supported on this end, disable it. * We can safely return -1 since there is no * chance that any data has been piped yet. + * EINVAL, however, is a bit special. + * If we're trying to splice from a KTLS + * socket, the kernel may return EINVAL + * to signal that the current TLS record + * is not application data, and that we + * have to call recvmsg() to get it. + * This is not really an error, and doesn't + * mean we won't be able to splice later. + * Choosing EINVAL there is a bit unfortunate, + * because it can mean many things, but we + * should not get it for any other reason. */ - retval = -1; + if (errno != EINVAL) + retval = -1; goto leave; } else if (errno == EINTR) { @@ -132,9 +144,11 @@ int raw_sock_to_pipe(struct connection *conn, void *xprt_ctx, struct pipe *pipe, continue; } /* here we have another error */ - conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_rcv_err); - conn->flags |= CO_FL_ERROR; - conn_set_errno(conn, errno); + if (errno != EINVAL) { + conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_rcv_err); + conn->flags |= CO_FL_ERROR; + conn_set_errno(conn, errno); + } break; } /* ret <= 0 */