rx: For AFS_RXERRQ_ENV, retry sendmsg on error 24/14424/4
authorAndrew Deason <adeason@sinenomine.net>
Mon, 2 Nov 2020 19:52:25 +0000 (13:52 -0600)
committerBenjamin Kaduk <kaduk@mit.edu>
Fri, 18 Dec 2020 16:54:51 +0000 (11:54 -0500)
commit5c9234694543f206174d30e21886286d419fd8df
treef83b716f8075c630b1324a414921bca6db16fd34
parenteff7fa4b2eb9a3001dc18dca157ccbd5f19f89b6
rx: For AFS_RXERRQ_ENV, retry sendmsg on error

When AFS_RXERRQ_ENV is defined, we currently end up doing something
like this for our sendmsg abstractions:

    if (sendmsg(...) < 0) {
        while (rxi_HandleSocketError(sock))
            ;
        return error;
    }
    return success;

This means that when sendmsg() returns an error, we process the socket
error queue before returning an error.

The problem with this is that when we receive an ICMP error on our
socket, it creates a pending socket error that is returned for any
operation on the socket. So, if we receive an ICMP error after trying
to contact any peer, sendmsg() could return an error when trying to
send for any other peer. Even though there is no issue preventing us
from sending the packet, we'll fail to actually send the packet
because sendmsg() returned an error. This effectively causes an extra
outgoing packet drop, possibly delaying the related RPC.

To avoid this, change Rx to retry the sendmsg call when it returns an
error, since the error may be due to an unrelated ICMP error.

To avoid needing to implement this retry loop in multiple places, move
around our sendmsg code for AFS_RXERRQ_ENV, so that the higher-level
function rxi_NetSend performs the retry and checks for socket errors
(instead of the lower-level rxi_Sendmsg or osi_NetSend). Also change
our functions to process socket errors to be more consistent between
kernel and userspace: now we always have rxi_HandleSocketErrors, which
runs a loop around the platform-specific osi_HandleSocketError.

With this commit, osi_HandleSocketError is now required to be
implemented when AFS_RXERRQ_ENV is defined. We hadn't been
implementing this for UKERNEL, so just turn off AFS_RXERRQ_ENV for
UKERNEL.

Thanks to mbarbosa@sinenomine.net for discovering and providing
information about the relevant issue.

Change-Id: Iccceddcd2d28992ed7a00dc308816a0cb1a0195f
Reviewed-on: https://gerrit.openafs.org/14424
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
src/config/param.linux26.h
src/rx/LINUX/rx_knet.c
src/rx/rx.c
src/rx/rx_internal.h
src/rx/rx_lwp.c
src/rx/rx_prototypes.h
src/rx/rx_pthread.c
src/rx/rx_user.c