Commit bb91c1a087ed29ceb5b25b9c210c6665e13c36eb

Authored by Hannes Reinecke
Committed by Nicholas Bellinger
1 parent 340dbf729c

target_core_alua: validate ALUA state transition

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@suse.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>

Showing 1 changed file with 45 additions and 10 deletions Side-by-side Diff

drivers/target/target_core_alua.c
... ... @@ -41,11 +41,14 @@
41 41 #include "target_core_alua.h"
42 42 #include "target_core_ua.h"
43 43  
44   -static sense_reason_t core_alua_check_transition(int state, int *primary);
  44 +static sense_reason_t core_alua_check_transition(int state, int valid,
  45 + int *primary);
45 46 static int core_alua_set_tg_pt_secondary_state(
46 47 struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem,
47 48 struct se_port *port, int explicit, int offline);
48 49  
  50 +static char *core_alua_dump_state(int state);
  51 +
49 52 static u16 alua_lu_gps_counter;
50 53 static u32 alua_lu_gps_count;
51 54  
... ... @@ -210,7 +213,7 @@
210 213 unsigned char *ptr;
211 214 sense_reason_t rc = TCM_NO_SENSE;
212 215 u32 len = 4; /* Skip over RESERVED area in header */
213   - int alua_access_state, primary = 0;
  216 + int alua_access_state, primary = 0, valid_states;
214 217 u16 tg_pt_id, rtpi;
215 218  
216 219 if (!l_port)
... ... @@ -252,6 +255,7 @@
252 255 rc = TCM_UNSUPPORTED_SCSI_OPCODE;
253 256 goto out;
254 257 }
  258 + valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states;
255 259  
256 260 ptr = &buf[4]; /* Skip over RESERVED area in header */
257 261  
... ... @@ -263,7 +267,8 @@
263 267 * the state is a primary or secondary target port asymmetric
264 268 * access state.
265 269 */
266   - rc = core_alua_check_transition(alua_access_state, &primary);
  270 + rc = core_alua_check_transition(alua_access_state,
  271 + valid_states, &primary);
267 272 if (rc) {
268 273 /*
269 274 * If the SET TARGET PORT GROUPS attempts to establish
270 275  
271 276  
272 277  
273 278  
274 279  
... ... @@ -618,17 +623,31 @@
618 623 * Check implicit and explicit ALUA state change request.
619 624 */
620 625 static sense_reason_t
621   -core_alua_check_transition(int state, int *primary)
  626 +core_alua_check_transition(int state, int valid, int *primary)
622 627 {
  628 + /*
  629 + * OPTIMIZED, NON-OPTIMIZED, STANDBY and UNAVAILABLE are
  630 + * defined as primary target port asymmetric access states.
  631 + */
623 632 switch (state) {
624 633 case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED:
  634 + if (!(valid & ALUA_AO_SUP))
  635 + goto not_supported;
  636 + *primary = 1;
  637 + break;
625 638 case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
  639 + if (!(valid & ALUA_AN_SUP))
  640 + goto not_supported;
  641 + *primary = 1;
  642 + break;
626 643 case ALUA_ACCESS_STATE_STANDBY:
  644 + if (!(valid & ALUA_S_SUP))
  645 + goto not_supported;
  646 + *primary = 1;
  647 + break;
627 648 case ALUA_ACCESS_STATE_UNAVAILABLE:
628   - /*
629   - * OPTIMIZED, NON-OPTIMIZED, STANDBY and UNAVAILABLE are
630   - * defined as primary target port asymmetric access states.
631   - */
  649 + if (!(valid & ALUA_U_SUP))
  650 + goto not_supported;
632 651 *primary = 1;
633 652 break;
634 653 case ALUA_ACCESS_STATE_OFFLINE:
635 654  
636 655  
... ... @@ -636,14 +655,27 @@
636 655 * OFFLINE state is defined as a secondary target port
637 656 * asymmetric access state.
638 657 */
  658 + if (!(valid & ALUA_O_SUP))
  659 + goto not_supported;
639 660 *primary = 0;
640 661 break;
  662 + case ALUA_ACCESS_STATE_TRANSITION:
  663 + /*
  664 + * Transitioning is set internally, and
  665 + * cannot be selected manually.
  666 + */
  667 + goto not_supported;
641 668 default:
642 669 pr_err("Unknown ALUA access state: 0x%02x\n", state);
643 670 return TCM_INVALID_PARAMETER_LIST;
644 671 }
645 672  
646 673 return 0;
  674 +
  675 +not_supported:
  676 + pr_err("ALUA access state %s not supported",
  677 + core_alua_dump_state(state));
  678 + return TCM_INVALID_PARAMETER_LIST;
647 679 }
648 680  
649 681 static char *core_alua_dump_state(int state)
... ... @@ -659,6 +691,8 @@
659 691 return "Unavailable";
660 692 case ALUA_ACCESS_STATE_OFFLINE:
661 693 return "Offline";
  694 + case ALUA_ACCESS_STATE_TRANSITION:
  695 + return "Transitioning";
662 696 default:
663 697 return "Unknown";
664 698 }
665 699  
... ... @@ -884,9 +918,10 @@
884 918 struct t10_alua_lu_gp_member *lu_gp_mem, *local_lu_gp_mem;
885 919 struct t10_alua_tg_pt_gp *tg_pt_gp;
886 920 unsigned char *md_buf;
887   - int primary;
  921 + int primary, valid_states;
888 922  
889   - if (core_alua_check_transition(new_state, &primary) != 0)
  923 + valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states;
  924 + if (core_alua_check_transition(new_state, valid_states, &primary) != 0)
890 925 return -EINVAL;
891 926  
892 927 md_buf = kzalloc(l_tg_pt_gp->tg_pt_gp_md_buf_len, GFP_KERNEL);