• Mike Christie's avatar
    target: fix race during implicit transition work flushes · 760bf578
    Mike Christie authored
    This fixes the following races:
    
    1. core_alua_do_transition_tg_pt could have read
    tg_pt_gp_alua_access_state and gone into this if chunk:
    
    if (!explicit &&
            atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state) ==
               ALUA_ACCESS_STATE_TRANSITION) {
    
    and then core_alua_do_transition_tg_pt_work could update the
    state. core_alua_do_transition_tg_pt would then only set
    tg_pt_gp_alua_pending_state and the tg_pt_gp_alua_access_state would
    not get updated with the second calls state.
    
    2. core_alua_do_transition_tg_pt could be setting
    tg_pt_gp_transition_complete while the tg_pt_gp_transition_work
    is already completing. core_alua_do_transition_tg_pt then waits on the
    completion that will never be called.
    
    To handle these issues, we just call flush_work which will return when
    core_alua_do_transition_tg_pt_work has completed so there is no need
    to do the complete/wait. And, if core_alua_do_transition_tg_pt_work
    was running, instead of trying to sneak in the state change, we just
    schedule up another core_alua_do_transition_tg_pt_work call.
    
    Note that this does not handle a possible race where there are multiple
    threads call core_alua_do_transition_tg_pt at the same time. I think
    we need a mutex in target_tg_pt_gp_alua_access_state_store.
    Signed-off-by: default avatarMike Christie <mchristi@redhat.com>
    Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
    760bf578
target_core_alua.c 61.9 KB