lkml.org 
[lkml]   [2017]   [Dec]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 038/177] rxrpc: Wake up the transmitter if Rx window size increases on the peer
    Date
    4.9-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: David Howells <dhowells@redhat.com>


    [ Upstream commit 702f2ac87a9a8da23bf8506466bc70175fc970b2 ]

    The RxRPC ACK packet may contain an extension that includes the peer's
    current Rx window size for this call. We adjust the local Tx window size
    to match. However, the transmitter can stall if the receive window is
    reduced to 0 by the peer and then reopened.

    This is because the normal way that the transmitter is re-energised is by
    dropping something out of our Tx queue and thus making space. When a
    single gap is made, the transmitter is woken up. However, because there's
    nothing in the Tx queue at this point, this doesn't happen.

    To fix this, perform a wake_up() any time we see the peer's Rx window size
    increasing.

    The observable symptom is that calls start failing on ETIMEDOUT and the
    following:

    kAFS: SERVER DEAD state=-62

    appears in dmesg.

    Signed-off-by: David Howells <dhowells@redhat.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    net/rxrpc/input.c | 15 ++++++++++++---
    1 file changed, 12 insertions(+), 3 deletions(-)

    --- a/net/rxrpc/input.c
    +++ b/net/rxrpc/input.c
    @@ -649,6 +649,7 @@ static void rxrpc_input_ackinfo(struct r
    struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
    struct rxrpc_peer *peer;
    unsigned int mtu;
    + bool wake = false;
    u32 rwind = ntohl(ackinfo->rwind);

    _proto("Rx ACK %%%u Info { rx=%u max=%u rwin=%u jm=%u }",
    @@ -656,9 +657,14 @@ static void rxrpc_input_ackinfo(struct r
    ntohl(ackinfo->rxMTU), ntohl(ackinfo->maxMTU),
    rwind, ntohl(ackinfo->jumbo_max));

    - if (rwind > RXRPC_RXTX_BUFF_SIZE - 1)
    - rwind = RXRPC_RXTX_BUFF_SIZE - 1;
    - call->tx_winsize = rwind;
    + if (call->tx_winsize != rwind) {
    + if (rwind > RXRPC_RXTX_BUFF_SIZE - 1)
    + rwind = RXRPC_RXTX_BUFF_SIZE - 1;
    + if (rwind > call->tx_winsize)
    + wake = true;
    + call->tx_winsize = rwind;
    + }
    +
    if (call->cong_ssthresh > rwind)
    call->cong_ssthresh = rwind;

    @@ -672,6 +678,9 @@ static void rxrpc_input_ackinfo(struct r
    spin_unlock_bh(&peer->lock);
    _net("Net MTU %u (maxdata %u)", peer->mtu, peer->maxdata);
    }
    +
    + if (wake)
    + wake_up(&call->waitq);
    }

    /*

    \
     
     \ /
      Last update: 2017-12-18 18:32    [W:4.267 / U:0.144 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site