• Philipp Reisner's avatar
    drbd: fix race between disconnect and receive_state · b8853dbd
    Philipp Reisner authored
    If the asender thread, or request_timer_fn(), or some other part of
    the code, decided to drop the connection (because of timeout or other),
    but the receiver just now was processing a P_STATE packet, there was a
    chance that receive_state() would do a hard state change
    "re-establishing" an already failed connection without additional handshake.
    
    Log excerpt:
      Remote failed to finish a request within ko-count * timeout
      peer( Secondary -> Unknown ) conn( Connected -> Timeout ) pdsk( UpToDate -> DUnknown )
      asender terminated
      ...
      peer( Unknown -> Secondary ) conn( Timeout -> Connected ) pdsk( DUnknown -> UpToDate ) peer_isp( 0 -> 1 )
      ...
      Connection closed
      peer( Secondary -> Unknown ) conn( Connected -> Unconnected ) pdsk( UpToDate -> DUnknown ) peer_isp( 1 -> 0 )
      receiver terminated
    
    Impact:
    while the connection state is erroneously "Connected",
    requests may be queued and even sent,
    which would never be acknowledged,
    and may have been missed by the cleanup.
    These requests would never be completed.
    
    The next drbd_suspend_io() will then lock up,
    waiting forever for these requests to complete.
    
    Fixed in several code paths:
      Make sure the connection state is NetworkFailure or worse
      before starting the cleanup in drbd_disconnect().
      This should make sure the cleanup won't miss any requests.
    
      Disallow receive_state() to "upgrade" the connection state
      from an error state. This will make sure the "illegal" state
      transition won't happen.
    
      For all connection failure states,
      relax the safe-guard in sanitize_state() again
      to silently mask out those state changes
      (e.g. Timeout -> Connected becomes Timeout -> Timeout).
    
     Note by Philipp Reisner:
      The 3rd chunk described as "relax the safe-guard..."
      is not there in 8.4 as it is relaxed to the maximum in
      8.4 already
    Signed-off-by: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
    Signed-off-by: default avatarLars Ellenberg <lars.ellenberg@linbit.com>
    b8853dbd
drbd_receiver.c 143 KB