mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
rxrpc: Fix return in rxrpc_recvmsg_data() for service calls
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.
rxperf_deliver_to_call() also has to be altered to call
rxrpc_kernel_recv_data() to collect the final ACK on a service call as does
afs_deliver_to_call().
Fixes: d001648ec7 ("rxrpc: Don't expose skbs to in-kernel users [ver #2]")
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 <jaltman@auristor.com>
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
Link: https://patch.msgid.link/20261006133011.531806-10-dhowells@redhat.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
41eb0af096
commit
18a71e111c
|
|
@ -909,10 +909,15 @@ The kernel interface functions are as follows:
|
|||
want_more should be true if further data will be required after this is
|
||||
satisfied and false if this is the last item of the receive phase.
|
||||
|
||||
There are three normal returns: 0 if the buffer was filled and want_more
|
||||
was true; 1 if the buffer was filled, the last DATA packet has been
|
||||
emptied and want_more was false; and -EAGAIN if the function needs to be
|
||||
called again.
|
||||
For client calls, there are three normal returns: 0 if the buffer was
|
||||
filled and want_more was true; 1 if the buffer was filled, the last DATA
|
||||
packet has been emptied and want_more was false; and -EAGAIN if the
|
||||
function needs to be called again.
|
||||
|
||||
For service calls, there are four normal returns: 0 and -EAGAIN are the
|
||||
same as for client calls; 2 indicates that the last DATA packet of the
|
||||
request has been received, want_more was false and the call is still in
|
||||
progress; and 1 indicates that the call is now successfully complete.
|
||||
|
||||
If the last DATA packet is processed but the buffer contains less than
|
||||
the amount requested, EBADMSG is returned. If want_more wasn't set, but
|
||||
|
|
|
|||
|
|
@ -541,7 +541,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)
|
||||
|
|
@ -934,7 +934,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);
|
||||
|
|
|
|||
|
|
@ -638,9 +638,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,
|
||||
|
|
@ -679,6 +681,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;
|
||||
|
|
|
|||
|
|
@ -293,8 +293,20 @@ static void rxperf_deliver_to_call(struct work_struct *work)
|
|||
state == RXPERF_CALL_SV_AWAIT_ACK
|
||||
) {
|
||||
if (state == RXPERF_CALL_SV_AWAIT_ACK) {
|
||||
if (!rxrpc_kernel_check_life(rxperf_socket, call->rxcall))
|
||||
size_t len = 0;
|
||||
iov_iter_kvec(&call->iter, ITER_DEST, NULL, 0, 0);
|
||||
ret = rxrpc_kernel_recv_data(rxperf_socket,
|
||||
call->rxcall, &call->iter,
|
||||
&len, false, &remote_abort,
|
||||
&call->service_id);
|
||||
|
||||
if (ret == -EAGAIN || ret == 2)
|
||||
return;
|
||||
if (ret < 0 || ret == 1) {
|
||||
if (ret == 1)
|
||||
ret = 0;
|
||||
goto call_complete;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -369,7 +381,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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user