On Wed, 2013-10-16 at 09:20 +0200, Hannes Reinecke wrote:
> Use a workqueue for processing ALUA state transitions; this allows
> us to process implicit delay properly.
> 
> Signed-off-by: Hannes Reinecke <h...@suse.de>
> ---
>  drivers/target/target_core_alua.c | 174 
> +++++++++++++++++++++++++++-----------
>  include/target/target_core_base.h |   4 +
>  2 files changed, 128 insertions(+), 50 deletions(-)
> 

<SNIP>

> +static int core_alua_do_transition_tg_pt(
> +     struct t10_alua_tg_pt_gp *tg_pt_gp,
> +     int new_state,
> +     int explicit)
> +{
> +     struct se_device *dev = tg_pt_gp->tg_pt_gp_dev;
> +     DECLARE_COMPLETION_ONSTACK(wait);
> +
> +     /* Nothing to be done here */
> +     if (atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state) == new_state)
> +             return 0;
> +
> +     if (new_state == ALUA_ACCESS_STATE_TRANSITION)
> +             return -EAGAIN;
> +
> +     /*
> +      * Flush any pending transitions
> +      */
> +     if (!explicit && tg_pt_gp->tg_pt_gp_implicit_trans_secs &&
> +         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;
> +             flush_delayed_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
> +      * to ALUA_ACCESS_STATE_TRANSITION.
> +      */
> +     tg_pt_gp->tg_pt_gp_alua_previous_state =
> +             atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state);
> +     tg_pt_gp->tg_pt_gp_alua_pending_state = new_state;
> +
> +     atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
> +                     ALUA_ACCESS_STATE_TRANSITION);
> +     tg_pt_gp->tg_pt_gp_alua_access_status = (explicit) ?
> +                             ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG :
> +                             ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA;
> +
> +     /*
> +      * Check for the optional ALUA primary state transition delay
> +      */
> +     if (tg_pt_gp->tg_pt_gp_trans_delay_msecs != 0)
> +             msleep_interruptible(tg_pt_gp->tg_pt_gp_trans_delay_msecs);
> +
> +     /*
> +      * Take a reference for workqueue item
> +      */
> +     spin_lock(&dev->t10_alua.tg_pt_gps_lock);
> +     atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt);
> +     smp_mb__after_atomic_inc();
> +     spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
> +
> +     if (!explicit && tg_pt_gp->tg_pt_gp_implicit_trans_secs) {
> +             unsigned long transition_tmo;
> +
> +             transition_tmo = tg_pt_gp->tg_pt_gp_implicit_trans_secs * HZ;
> +             queue_delayed_work(tg_pt_gp->tg_pt_gp_dev->tmr_wq,
> +                                &tg_pt_gp->tg_pt_gp_transition_work,
> +                                transition_tmo);
> +     } else {
> +             tg_pt_gp->tg_pt_gp_transition_complete = &wait;
> +             queue_delayed_work(tg_pt_gp->tg_pt_gp_dev->tmr_wq,
> +                                &tg_pt_gp->tg_pt_gp_transition_work, 0);
> +             wait_for_completion(&wait);
> +             tg_pt_gp->tg_pt_gp_transition_complete = NULL;
> +     }

Mmm, the trans_delay_msecs delay seems a bit out of place now..

How about dropping it's usage with msleep_interruptible() above, and
instead combining it with the delay passed into queue_delayed_work()..?

--nab


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to