On Tue, 2013-12-17 at 09:18 +0100, Hannes Reinecke wrote: > As we now can modify the list of supported states we need to > validate the requested ALUA state when doing a state transition. > > Signed-off-by: Hannes Reinecke <hare@xxxxxxx> > --- > drivers/target/target_core_alua.c | 55 ++++++++++++++++++++++++++++++++------- > 1 file changed, 45 insertions(+), 10 deletions(-) > Applied to for-next. Thanks Hannes! --nab > diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c > index fdcee32..292ecce 100644 > --- a/drivers/target/target_core_alua.c > +++ b/drivers/target/target_core_alua.c > @@ -41,11 +41,14 @@ > #include "target_core_alua.h" > #include "target_core_ua.h" > > -static sense_reason_t core_alua_check_transition(int state, int *primary); > +static sense_reason_t core_alua_check_transition(int state, int valid, > + int *primary); > static int core_alua_set_tg_pt_secondary_state( > struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, > struct se_port *port, int explicit, int offline); > > +static char *core_alua_dump_state(int state); > + > static u16 alua_lu_gps_counter; > static u32 alua_lu_gps_count; > > @@ -210,7 +213,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) > unsigned char *ptr; > sense_reason_t rc = TCM_NO_SENSE; > u32 len = 4; /* Skip over RESERVED area in header */ > - int alua_access_state, primary = 0; > + int alua_access_state, primary = 0, valid_states; > u16 tg_pt_id, rtpi; > > if (!l_port) > @@ -252,6 +255,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) > rc = TCM_UNSUPPORTED_SCSI_OPCODE; > goto out; > } > + valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states; > > ptr = &buf[4]; /* Skip over RESERVED area in header */ > > @@ -263,7 +267,8 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) > * the state is a primary or secondary target port asymmetric > * access state. > */ > - rc = core_alua_check_transition(alua_access_state, &primary); > + rc = core_alua_check_transition(alua_access_state, > + valid_states, &primary); > if (rc) { > /* > * If the SET TARGET PORT GROUPS attempts to establish > @@ -618,17 +623,31 @@ out: > * Check implicit and explicit ALUA state change request. > */ > static sense_reason_t > -core_alua_check_transition(int state, int *primary) > +core_alua_check_transition(int state, int valid, int *primary) > { > + /* > + * OPTIMIZED, NON-OPTIMIZED, STANDBY and UNAVAILABLE are > + * defined as primary target port asymmetric access states. > + */ > switch (state) { > case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED: > + if (!(valid & ALUA_AO_SUP)) > + goto not_supported; > + *primary = 1; > + break; > case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: > + if (!(valid & ALUA_AN_SUP)) > + goto not_supported; > + *primary = 1; > + break; > case ALUA_ACCESS_STATE_STANDBY: > + if (!(valid & ALUA_S_SUP)) > + goto not_supported; > + *primary = 1; > + break; > case ALUA_ACCESS_STATE_UNAVAILABLE: > - /* > - * OPTIMIZED, NON-OPTIMIZED, STANDBY and UNAVAILABLE are > - * defined as primary target port asymmetric access states. > - */ > + if (!(valid & ALUA_U_SUP)) > + goto not_supported; > *primary = 1; > break; > case ALUA_ACCESS_STATE_OFFLINE: > @@ -636,14 +655,27 @@ core_alua_check_transition(int state, int *primary) > * OFFLINE state is defined as a secondary target port > * asymmetric access state. > */ > + if (!(valid & ALUA_O_SUP)) > + goto not_supported; > *primary = 0; > break; > + case ALUA_ACCESS_STATE_TRANSITION: > + /* > + * Transitioning is set internally, and > + * cannot be selected manually. > + */ > + goto not_supported; > default: > pr_err("Unknown ALUA access state: 0x%02x\n", state); > return TCM_INVALID_PARAMETER_LIST; > } > > return 0; > + > +not_supported: > + pr_err("ALUA access state %s not supported", > + core_alua_dump_state(state)); > + return TCM_INVALID_PARAMETER_LIST; > } > > static char *core_alua_dump_state(int state) > @@ -659,6 +691,8 @@ static char *core_alua_dump_state(int state) > return "Unavailable"; > case ALUA_ACCESS_STATE_OFFLINE: > return "Offline"; > + case ALUA_ACCESS_STATE_TRANSITION: > + return "Transitioning"; > default: > return "Unknown"; > } > @@ -884,9 +918,10 @@ int core_alua_do_port_transition( > struct t10_alua_lu_gp_member *lu_gp_mem, *local_lu_gp_mem; > struct t10_alua_tg_pt_gp *tg_pt_gp; > unsigned char *md_buf; > - int primary; > + int primary, valid_states; > > - if (core_alua_check_transition(new_state, &primary) != 0) > + valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states; > + if (core_alua_check_transition(new_state, valid_states, &primary) != 0) > return -EINVAL; > > md_buf = kzalloc(l_tg_pt_gp->tg_pt_gp_md_buf_len, GFP_KERNEL); -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html