• David Howells's avatar
    afs: Adjust ACK interpretation to try and cope with NAT · adc9613f
    David Howells authored
    If a client's address changes, say if it is NAT'd, this can disrupt an in
    progress operation.  For most operations, this is not much of a problem,
    but StoreData can be different as some servers modify the target file as
    the data comes in, so if a store request is disrupted, the file can get
    corrupted on the server.
    
    The problem is that the server doesn't recognise packets that come after
    the change of address as belonging to the original client and will bounce
    them, either by sending an OUT_OF_SEQUENCE ACK to the apparent new call if
    the packet number falls within the initial sequence number window of a call
    or by sending an EXCEEDS_WINDOW ACK if it falls outside and then aborting
    it.  In both cases, firstPacket will be 1 and previousPacket will be 0 in
    the ACK information.
    
    Fix this by the following means:
    
     (1) If a client call receives an EXCEEDS_WINDOW ACK with firstPacket as 1
         and previousPacket as 0, assume this indicates that the server saw the
         incoming packets from a different peer and thus as a different call.
         Fail the call with error -ENETRESET.
    
     (2) Also fail the call if a similar OUT_OF_SEQUENCE ACK occurs if the
         first packet has been hard-ACK'd.  If it hasn't been hard-ACK'd, the
         ACK packet will cause it to get retransmitted, so the call will just
         be repeated.
    
     (3) Make afs_select_fileserver() treat -ENETRESET as a straight fail of
         the operation.
    
     (4) Prioritise the error code over things like -ECONNRESET as the server
         did actually respond.
    
     (5) Make writeback treat -ENETRESET as a retryable error and make it
         redirty all the pages involved in a write so that the VM will retry.
    
    Note that there is still a circumstance that I can't easily deal with: if
    the operation is fully received and processed by the server, but the reply
    is lost due to address change.  There's no way to know if the op happened.
    We can examine the server, but a conflicting change could have been made by
    a third party - and we can't tell the difference.  In such a case, a
    message like:
    
        kAFS: vnode modified {100058:146266} b7->b8 YFS.StoreData64 (op=2646a)
    
    will be logged to dmesg on the next op to touch the file and the client
    will reset the inode state, including invalidating clean parts of the
    pagecache.
    Reported-by: default avatarMarc Dionne <marc.dionne@auristor.com>
    Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
    cc: linux-afs@lists.infradead.org
    Link: http://lists.infradead.org/pipermail/linux-afs/2021-December/004811.html # v1
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    adc9613f
misc.c 4.73 KB