[PATCH net v11 10/17] rxrpc: Fix return in rxrpc_recvmsg_data() for service calls
From: David Howells <dhowells@redhat.com>
Date: 2026-09-23 13:38:15
Also in:
lkml, stable
Subsystem:
afs filesystem, filesystems (vfs and infrastructure), networking [general], rxrpc sockets (af_rxrpc), the rest · Maintainers:
David Howells, Marc Dionne, Alexander Viro, Christian Brauner, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
When rxrpc_recvmsg_data() gets called on a service call that has received all of the request, RXRPC_CALL_RECVMSG_READ_ALL has been set, and this causes rxrpc_recvmsg_data() to jump straight out, indicating the end of the call (ie. rxrpc_kernel_recv_data() returns 1) without waiting for the call to be processed or the reply to be transmitted. Link: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260914151340.3227501-1-dhowells%40redhat.com Signed-off-by: David Howells <dhowells@redhat.com> cc: Marc Dionne <marc.dionne@auristor.com> cc: Jeffrey Altman <redacted> cc: Eric Dumazet <edumazet@google.com> cc: "David S. Miller" <davem@davemloft.net> cc: Jakub Kicinski <kuba@kernel.org> cc: Paolo Abeni <pabeni@redhat.com> cc: Simon Horman <horms@kernel.org> cc: linux-afs@lists.infradead.org cc: stable@vger.kernel.org --- fs/afs/rxrpc.c | 4 ++-- net/rxrpc/recvmsg.c | 13 ++++++++++--- net/rxrpc/rxperf.c | 4 ++-- 3 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
index 0b9027549580..8e7a83a95ac9 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c@@ -542,7 +542,7 @@ void afs_deliver_to_call(struct afs_call *call) &call->service_id); trace_afs_receive_data(call, &call->def_iter, false, ret); - if (ret == -EINPROGRESS || ret == -EAGAIN) + if (ret == -EAGAIN || ret == 2) return; if (ret < 0 || ret == 1) { if (ret == 1)
@@ -932,7 +932,7 @@ int afs_extract_data(struct afs_call *call, bool want_more) return ret; state = READ_ONCE(call->state); - if (ret == 1) { + if (ret == 1 || ret == 2) { switch (state) { case AFS_CALL_CL_AWAIT_REPLY: afs_set_call_state(call, state, AFS_CALL_CL_PROC_REPLY);
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index efcba4b2e74f..716f7f47d7e4 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c@@ -637,9 +637,11 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, * Note that we may return %-EAGAIN to drain empty packets at the end * of the data, even if we've already copied over the requested data. * - * Return: %0 if got what was asked for and there's more available, %1 - * if we got what was asked for and we're at the end of the data and - * %-EAGAIN if we need more data. + * Return: %0 if got what was asked for and there's more available, %1 if we + * got what was asked for and we're at the end of the call, %2 if a service + * call received all of the request but is still in progress and %-EAGAIN if we + * need more data. A variety of other errors can be returned if the call + * completed with failure. */ int rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call, struct iov_iter *iter, size_t *_len,
@@ -678,6 +680,11 @@ int rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call, read_phase_complete: ret = 1; + if (rxrpc_is_service_call(call)) { + if (rxrpc_call_is_complete(call)) + goto call_failed; + ret = 2; + } out: if (_service) *_service = call->dest_srx.srx_service;
diff --git a/net/rxrpc/rxperf.c b/net/rxrpc/rxperf.c
index 5042e8bfca55..6ccfd40b5388 100644
--- a/net/rxrpc/rxperf.c
+++ b/net/rxrpc/rxperf.c@@ -300,7 +300,7 @@ static void rxperf_deliver_to_call(struct work_struct *work) &len, false, &remote_abort, &call->service_id); - if (ret == -EINPROGRESS || ret == -EAGAIN) + if (ret == -EAGAIN || ret == 2) return; if (ret < 0 || ret == 1) { if (ret == 1)
@@ -379,7 +379,7 @@ static int rxperf_extract_data(struct rxperf_call *call, bool want_more) if (ret == 0 || ret == -EAGAIN) return ret; - if (ret == 1) { + if (ret == 1 || ret == 2) { switch (call->state) { case RXPERF_CALL_SV_AWAIT_REQUEST: rxperf_set_call_state(call, RXPERF_CALL_SV_REPLYING);