• Trond Myklebust's avatar
    SUNRPC: Fix a data corruption issue when retransmitting RPC calls · a6b31d18
    Trond Myklebust authored
    The following scenario can cause silent data corruption when doing
    NFS writes. It has mainly been observed when doing database writes
    using O_DIRECT.
    
    1) The RPC client uses sendpage() to do zero-copy of the page data.
    2) Due to networking issues, the reply from the server is delayed,
       and so the RPC client times out.
    
    3) The client issues a second sendpage of the page data as part of
       an RPC call retransmission.
    
    4) The reply to the first transmission arrives from the server
       _before_ the client hardware has emptied the TCP socket send
       buffer.
    5) After processing the reply, the RPC state machine rules that
       the call to be done, and triggers the completion callbacks.
    6) The application notices the RPC call is done, and reuses the
       pages to store something else (e.g. a new write).
    
    7) The client NIC drains the TCP socket send buffer. Since the
       page data has now changed, it reads a corrupted version of the
       initial RPC call, and puts it on the wire.
    
    This patch fixes the problem in the following manner:
    
    The ordering guarantees of TCP ensure that when the server sends a
    reply, then we know that the _first_ transmission has completed. Using
    zero-copy in that situation is therefore safe.
    If a time out occurs, we then send the retransmission using sendmsg()
    (i.e. no zero-copy), We then know that the socket contains a full copy of
    the data, and so it will retransmit a faithful reproduction even if the
    RPC call completes, and the application reuses the O_DIRECT buffer in
    the meantime.
    Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
    Cc: stable@vger.kernel.org
    a6b31d18
xprtsock.c 80.3 KB