aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2013-12-17 03:18:43 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2013-12-17 13:30:26 -0500
commitbb91c1a087ed29ceb5b25b9c210c6665e13c36eb (patch)
treeb4b86f4accb7e5e810a181b4e19cc1b86ba0186f
parent340dbf729c3395cf1317890d033aa9ac7347766c (diff)
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>
-rw-r--r--drivers/target/target_core_alua.c55
1 files changed, 45 insertions, 10 deletions
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index fdcee326bfbc..292ecce98d1f 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -41,11 +41,14 @@
41#include "target_core_alua.h" 41#include "target_core_alua.h"
42#include "target_core_ua.h" 42#include "target_core_ua.h"
43 43
44static sense_reason_t core_alua_check_transition(int state, int *primary); 44static sense_reason_t core_alua_check_transition(int state, int valid,
45 int *primary);
45static int core_alua_set_tg_pt_secondary_state( 46static int core_alua_set_tg_pt_secondary_state(
46 struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, 47 struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem,
47 struct se_port *port, int explicit, int offline); 48 struct se_port *port, int explicit, int offline);
48 49
50static char *core_alua_dump_state(int state);
51
49static u16 alua_lu_gps_counter; 52static u16 alua_lu_gps_counter;
50static u32 alua_lu_gps_count; 53static u32 alua_lu_gps_count;
51 54
@@ -210,7 +213,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
210 unsigned char *ptr; 213 unsigned char *ptr;
211 sense_reason_t rc = TCM_NO_SENSE; 214 sense_reason_t rc = TCM_NO_SENSE;
212 u32 len = 4; /* Skip over RESERVED area in header */ 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 u16 tg_pt_id, rtpi; 217 u16 tg_pt_id, rtpi;
215 218
216 if (!l_port) 219 if (!l_port)
@@ -252,6 +255,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
252 rc = TCM_UNSUPPORTED_SCSI_OPCODE; 255 rc = TCM_UNSUPPORTED_SCSI_OPCODE;
253 goto out; 256 goto out;
254 } 257 }
258 valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states;
255 259
256 ptr = &buf[4]; /* Skip over RESERVED area in header */ 260 ptr = &buf[4]; /* Skip over RESERVED area in header */
257 261
@@ -263,7 +267,8 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
263 * the state is a primary or secondary target port asymmetric 267 * the state is a primary or secondary target port asymmetric
264 * access state. 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 if (rc) { 272 if (rc) {
268 /* 273 /*
269 * If the SET TARGET PORT GROUPS attempts to establish 274 * If the SET TARGET PORT GROUPS attempts to establish
@@ -618,17 +623,31 @@ out:
618 * Check implicit and explicit ALUA state change request. 623 * Check implicit and explicit ALUA state change request.
619 */ 624 */
620static sense_reason_t 625static sense_reason_t
621core_alua_check_transition(int state, int *primary) 626core_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 switch (state) { 632 switch (state) {
624 case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED: 633 case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED:
634 if (!(valid & ALUA_AO_SUP))
635 goto not_supported;
636 *primary = 1;
637 break;
625 case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: 638 case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
639 if (!(valid & ALUA_AN_SUP))
640 goto not_supported;
641 *primary = 1;
642 break;
626 case ALUA_ACCESS_STATE_STANDBY: 643 case ALUA_ACCESS_STATE_STANDBY:
644 if (!(valid & ALUA_S_SUP))
645 goto not_supported;
646 *primary = 1;
647 break;
627 case ALUA_ACCESS_STATE_UNAVAILABLE: 648 case ALUA_ACCESS_STATE_UNAVAILABLE:
628 /* 649 if (!(valid & ALUA_U_SUP))
629 * OPTIMIZED, NON-OPTIMIZED, STANDBY and UNAVAILABLE are 650 goto not_supported;
630 * defined as primary target port asymmetric access states.
631 */
632 *primary = 1; 651 *primary = 1;
633 break; 652 break;
634 case ALUA_ACCESS_STATE_OFFLINE: 653 case ALUA_ACCESS_STATE_OFFLINE:
@@ -636,14 +655,27 @@ core_alua_check_transition(int state, int *primary)
636 * OFFLINE state is defined as a secondary target port 655 * OFFLINE state is defined as a secondary target port
637 * asymmetric access state. 656 * asymmetric access state.
638 */ 657 */
658 if (!(valid & ALUA_O_SUP))
659 goto not_supported;
639 *primary = 0; 660 *primary = 0;
640 break; 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 default: 668 default:
642 pr_err("Unknown ALUA access state: 0x%02x\n", state); 669 pr_err("Unknown ALUA access state: 0x%02x\n", state);
643 return TCM_INVALID_PARAMETER_LIST; 670 return TCM_INVALID_PARAMETER_LIST;
644 } 671 }
645 672
646 return 0; 673 return 0;
674
675not_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
649static char *core_alua_dump_state(int state) 681static char *core_alua_dump_state(int state)
@@ -659,6 +691,8 @@ static char *core_alua_dump_state(int state)
659 return "Unavailable"; 691 return "Unavailable";
660 case ALUA_ACCESS_STATE_OFFLINE: 692 case ALUA_ACCESS_STATE_OFFLINE:
661 return "Offline"; 693 return "Offline";
694 case ALUA_ACCESS_STATE_TRANSITION:
695 return "Transitioning";
662 default: 696 default:
663 return "Unknown"; 697 return "Unknown";
664 } 698 }
@@ -884,9 +918,10 @@ int core_alua_do_port_transition(
884 struct t10_alua_lu_gp_member *lu_gp_mem, *local_lu_gp_mem; 918 struct t10_alua_lu_gp_member *lu_gp_mem, *local_lu_gp_mem;
885 struct t10_alua_tg_pt_gp *tg_pt_gp; 919 struct t10_alua_tg_pt_gp *tg_pt_gp;
886 unsigned char *md_buf; 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 return -EINVAL; 925 return -EINVAL;
891 926
892 md_buf = kzalloc(l_tg_pt_gp->tg_pt_gp_md_buf_len, GFP_KERNEL); 927 md_buf = kzalloc(l_tg_pt_gp->tg_pt_gp_md_buf_len, GFP_KERNEL);