mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
target: fix race during implicit transition work flushes
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: Mike Christie <mchristi@redhat.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
parent
1ca4d4fa3b
commit
760bf578ed
1 changed files with 1 additions and 9 deletions
|
@ -1079,16 +1079,8 @@ static int core_alua_do_transition_tg_pt(
|
|||
/*
|
||||
* Flush any pending transitions
|
||||
*/
|
||||
if (!explicit && atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state) ==
|
||||
ALUA_ACCESS_STATE_TRANSITION) {
|
||||
/* Just in case */
|
||||
tg_pt_gp->tg_pt_gp_alua_pending_state = new_state;
|
||||
tg_pt_gp->tg_pt_gp_transition_complete = &wait;
|
||||
if (!explicit)
|
||||
flush_work(&tg_pt_gp->tg_pt_gp_transition_work);
|
||||
wait_for_completion(&wait);
|
||||
tg_pt_gp->tg_pt_gp_transition_complete = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the old primary ALUA access state, and set the current state
|
||||
|
|
Loading…
Reference in a new issue