Skip to contentSkip to conversation

ALUA update and Referrals support

PATCH Applied Hannes Reinecke 2 participants 31 messages Nov 19, 2013 – Dec 17, 2013

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

v2 cover ALUA update and Referrals support

Hi Nic,

here's the second version of my ALUA update & Referrals support patches. As per request I've split up the supported states into individual attributes, and while there I've also renamed the rather confusing 'alua_access_type' and 'alua_access_status' into 'alua_management_type' and 'alua_status_modification', respectively.

The other features are:

- Make supported states configurable:
We should make the list of supported ALUA states configurable, as some setups would possibly like to support a small subset of ALUA states only.
- Asynchronous transitioning: I've switched 'transitioning' handling to use a workqueue, that should allow us to simulate asynchronous transitioning modes. IE TCM should now be capable of handling requests while in transitioning, and properly terminate these with the correct sense code.
- Include target device descriptor in VPD page 83
For the ALUA device handler we'd need to identify the target device where a given target port belongs to. So include the respective values in the VPD page.

And, of course, referrals support.

Hannes Reinecke (18):
target core: rename (ex,im)plict -> (ex,im)plicit
target_core_alua: spellcheck
target_core_alua: Rename ALUA_ACCESS_STATE_OPTIMIZED
target_core_alua: Store supported ALUA states
target_core_alua: Make supported states configurable
target_core_configfs: split up ALUA supported states
target_core_configfs: Verbose ALUA state display
target_core_configfs: Split up ALUA access type
target_core: Rename alua_access_type in alua_mgmt_type
target_core: Rename alua_access_status to alua_status_modification
target_core_alua: Validate ALUA state transition
target_core_alua: Allocate ALUA metadata on demand
target_core_alua: store old and pending ALUA state
target_core_alua: Use workqueue for ALUA transitioning
target_core: simplify scsi_name_len calculation
target_core_spc: Include target device descriptor in VPD page 83
target_core_alua: Referrals infrastructure
target_core_alua: Referrals configfs integration

 drivers/target/target_core_alua.c      | 764 +++++++++++++++++++++++----------
 drivers/target/target_core_alua.h      |  55 ++-
 drivers/target/target_core_configfs.c  | 360 ++++++++++++++--
 drivers/target/target_core_device.c    |   9 +-
 drivers/target/target_core_file.c      |   2 +-
 drivers/target/target_core_pr.c        |  24 +-
 drivers/target/target_core_sbc.c       |   5 +-
 drivers/target/target_core_spc.c       |  84 +++-
 drivers/target/target_core_transport.c |  32 +-
 drivers/target/target_core_ua.h        |   2 +-
 include/scsi/scsi.h                    |   1 +
 include/target/target_core_base.h      |  34 +-
 12 files changed, 1050 insertions(+), 322 deletions(-)
Signature · 1 line
1.7.12.4
#1 lore raw

PATCH v2 1/18 target core: rename (ex,im)plict -> (ex,im)plicit

---
 drivers/target/target_core_alua.c      | 110 ++++++++++++++++-----------------
 drivers/target/target_core_alua.h      |  20 +++---
 drivers/target/target_core_configfs.c  |  26 ++++----
 drivers/target/target_core_device.c    |   6 +-
 drivers/target/target_core_file.c      |   2 +-
 drivers/target/target_core_pr.c        |  24 +++----
 drivers/target/target_core_spc.c       |   6 +-
 drivers/target/target_core_transport.c |   4 +-
 drivers/target/target_core_ua.h        |   2 +-
 include/target/target_core_base.h      |   2 +-
 10 files changed, 101 insertions(+), 101 deletions(-)
drivers/target/target_core_alua.c +55 -55
index 4724410..8297d37 100644
@@ -44,7 +44,7 @@
 static sense_reason_t core_alua_check_transition(int state, 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 explict, int offline);
+		struct se_port *port, int explicit, int offline);
 
 static u16 alua_lu_gps_counter;
 static u32 alua_lu_gps_count;
@@ -175,7 +175,7 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd)
 	if (ext_hdr != 0) {
 		buf[4] = 0x10;
 		/*
-		 * Set the implict transition time (in seconds) for the application
+		 * Set the implicit transition time (in seconds) for the application
 		 * client to use as a base for it's transition timeout value.
 		 *
 		 * Use the current tg_pt_gp_mem -> tg_pt_gp membership from the LUN
@@ -188,7 +188,7 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd)
 			spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 			tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
 			if (tg_pt_gp)
-				buf[5] = tg_pt_gp->tg_pt_gp_implict_trans_secs;
+				buf[5] = tg_pt_gp->tg_pt_gp_implicit_trans_secs;
 			spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 		}
 	}
@@ -199,7 +199,7 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd)
 }
 
 /*
- * SET_TARGET_PORT_GROUPS for explict ALUA operation.
+ * SET_TARGET_PORT_GROUPS for explicit ALUA operation.
  *
  * See spc4r17 section 6.35
  */
@@ -232,7 +232,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
 		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
 	/*
-	 * Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed
+	 * Determine if explicit ALUA via SET_TARGET_PORT_GROUPS is allowed
 	 * for the local tg_pt_gp.
 	 */
 	l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem;
@@ -251,9 +251,9 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
 	}
 	spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
 
-	if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA)) {
+	if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)) {
 		pr_debug("Unable to process SET_TARGET_PORT_GROUPS"
-				" while TPGS_EXPLICT_ALUA is disabled\n");
+				" while TPGS_EXPLICIT_ALUA is disabled\n");
 		rc = TCM_UNSUPPORTED_SCSI_OPCODE;
 		goto out;
 	}
@@ -620,7 +620,7 @@ out:
 }
 
 /*
- * Check implict and explict ALUA state change request.
+ * Check implicit and explicit ALUA state change request.
  */
 static sense_reason_t
 core_alua_check_transition(int state, int *primary)
@@ -676,10 +676,10 @@ char *core_alua_dump_status(int status)
 	switch (status) {
 	case ALUA_STATUS_NONE:
 		return "None";
-	case ALUA_STATUS_ALTERED_BY_EXPLICT_STPG:
-		return "Altered by Explict STPG";
-	case ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA:
-		return "Altered by Implict ALUA";
+	case ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG:
+		return "Altered by Explicit STPG";
+	case ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA:
+		return "Altered by Implicit ALUA";
 	default:
 		return "Unknown";
 	}
@@ -770,7 +770,7 @@ static int core_alua_do_transition_tg_pt(
 	struct se_node_acl *nacl,
 	unsigned char *md_buf,
 	int new_state,
-	int explict)
+	int explicit)
 {
 	struct se_dev_entry *se_deve;
 	struct se_lun_acl *lacl;
@@ -784,9 +784,9 @@ static int core_alua_do_transition_tg_pt(
 	old_state = atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_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 = (explict) ?
-				ALUA_STATUS_ALTERED_BY_EXPLICT_STPG :
-				ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA;
+	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
 	 */
@@ -821,12 +821,12 @@ static int core_alua_do_transition_tg_pt(
 			lacl = se_deve->se_lun_acl;
 			/*
 			 * se_deve->se_lun_acl pointer may be NULL for a
-			 * entry created without explict Node+MappedLUN ACLs
+			 * entry created without explicit Node+MappedLUN ACLs
 			 */
 			if (!lacl)
 				continue;
 
-			if (explict &&
+			if (explicit &&
 			   (nacl != NULL) && (nacl == lacl->se_lun_nacl) &&
 			   (l_port != NULL) && (l_port == port))
 				continue;
@@ -866,8 +866,8 @@ static int core_alua_do_transition_tg_pt(
 	atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, new_state);
 
 	pr_debug("Successful %s ALUA transition TG PT Group: %s ID: %hu"
-		" from primary access state %s to %s\n", (explict) ? "explict" :
-		"implict", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item),
+		" from primary access state %s to %s\n", (explicit) ? "explicit" :
+		"implicit", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item),
 		tg_pt_gp->tg_pt_gp_id, core_alua_dump_state(old_state),
 		core_alua_dump_state(new_state));
 
@@ -880,7 +880,7 @@ int core_alua_do_port_transition(
 	struct se_port *l_port,
 	struct se_node_acl *l_nacl,
 	int new_state,
-	int explict)
+	int explicit)
 {
 	struct se_device *dev;
 	struct se_port *port;
@@ -917,7 +917,7 @@ int core_alua_do_port_transition(
 		 * success.
 		 */
 		core_alua_do_transition_tg_pt(l_tg_pt_gp, l_port, l_nacl,
-					md_buf, new_state, explict);
+					md_buf, new_state, explicit);
 		atomic_dec(&lu_gp->lu_gp_ref_cnt);
 		smp_mb__after_atomic_dec();
 		kfree(md_buf);
@@ -970,7 +970,7 @@ int core_alua_do_port_transition(
 			 * success.
 			 */
 			core_alua_do_transition_tg_pt(tg_pt_gp, port,
-					nacl, md_buf, new_state, explict);
+					nacl, md_buf, new_state, explicit);
 
 			spin_lock(&dev->t10_alua.tg_pt_gps_lock);
 			atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
@@ -987,7 +987,7 @@ int core_alua_do_port_transition(
 	pr_debug("Successfully processed LU Group: %s all ALUA TG PT"
 		" Group IDs: %hu %s transition to primary state: %s\n",
 		config_item_name(&lu_gp->lu_gp_group.cg_item),
-		l_tg_pt_gp->tg_pt_gp_id, (explict) ? "explict" : "implict",
+		l_tg_pt_gp->tg_pt_gp_id, (explicit) ? "explicit" : "implicit",
 		core_alua_dump_state(new_state));
 
 	atomic_dec(&lu_gp->lu_gp_ref_cnt);
@@ -1034,7 +1034,7 @@ static int core_alua_update_tpg_secondary_metadata(
 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 explict,
+	int explicit,
 	int offline)
 {
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
@@ -1061,13 +1061,13 @@ static int core_alua_set_tg_pt_secondary_state(
 		atomic_set(&port->sep_tg_pt_secondary_offline, 0);
 
 	md_buf_len = tg_pt_gp->tg_pt_gp_md_buf_len;
-	port->sep_tg_pt_secondary_stat = (explict) ?
-			ALUA_STATUS_ALTERED_BY_EXPLICT_STPG :
-			ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA;
+	port->sep_tg_pt_secondary_stat = (explicit) ?
+			ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG :
+			ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA;
 
 	pr_debug("Successful %s ALUA transition TG PT Group: %s ID: %hu"
-		" to secondary access state: %s\n", (explict) ? "explict" :
-		"implict", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item),
+		" to secondary access state: %s\n", (explicit) ? "explicit" :
+		"implicit", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item),
 		tg_pt_gp->tg_pt_gp_id, (offline) ? "OFFLINE" : "ONLINE");
 
 	spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
@@ -1356,16 +1356,16 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev,
 	atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
 		ALUA_ACCESS_STATE_ACTIVE_OPTMIZED);
 	/*
-	 * Enable both explict and implict ALUA support by default
+	 * Enable both explicit and implicit ALUA support by default
 	 */
 	tg_pt_gp->tg_pt_gp_alua_access_type =
-			TPGS_EXPLICT_ALUA | TPGS_IMPLICT_ALUA;
+			TPGS_EXPLICIT_ALUA | TPGS_IMPLICIT_ALUA;
 	/*
 	 * Set the default Active/NonOptimized Delay in milliseconds
 	 */
 	tg_pt_gp->tg_pt_gp_nonop_delay_msecs = ALUA_DEFAULT_NONOP_DELAY_MSECS;
 	tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS;
-	tg_pt_gp->tg_pt_gp_implict_trans_secs = ALUA_DEFAULT_IMPLICT_TRANS_SECS;
+	tg_pt_gp->tg_pt_gp_implicit_trans_secs = ALUA_DEFAULT_IMPLICIT_TRANS_SECS;
 
 	if (def_group) {
 		spin_lock(&dev->t10_alua.tg_pt_gps_lock);
@@ -1465,7 +1465,7 @@ void core_alua_free_tg_pt_gp(
 	 * been called from target_core_alua_drop_tg_pt_gp().
 	 *
 	 * Here we remove *tg_pt_gp from the global list so that
-	 * no assications *OR* explict ALUA via SET_TARGET_PORT_GROUPS
+	 * no assications *OR* explicit ALUA via SET_TARGET_PORT_GROUPS
 	 * can be made while we are releasing struct t10_alua_tg_pt_gp.
 	 */
 	spin_lock(&dev->t10_alua.tg_pt_gps_lock);
@@ -1740,13 +1740,13 @@ ssize_t core_alua_show_access_type(
 	struct t10_alua_tg_pt_gp *tg_pt_gp,
 	char *page)
 {
-	if ((tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA) &&
-	    (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICT_ALUA))
-		return sprintf(page, "Implict and Explict\n");
-	else if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICT_ALUA)
-		return sprintf(page, "Implict\n");
-	else if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA)
-		return sprintf(page, "Explict\n");
+	if ((tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA) &&
+	    (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICIT_ALUA))
+		return sprintf(page, "Implicit and Explicit\n");
+	else if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICIT_ALUA)
+		return sprintf(page, "Implicit\n");
+	else if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)
+		return sprintf(page, "Explicit\n");
 	else
 		return sprintf(page, "None\n");
 }
@@ -1771,11 +1771,11 @@ ssize_t core_alua_store_access_type(
 	}
 	if (tmp == 3)
 		tg_pt_gp->tg_pt_gp_alua_access_type =
-			TPGS_IMPLICT_ALUA | TPGS_EXPLICT_ALUA;
+			TPGS_IMPLICIT_ALUA | TPGS_EXPLICIT_ALUA;
 	else if (tmp == 2)
-		tg_pt_gp->tg_pt_gp_alua_access_type = TPGS_EXPLICT_ALUA;
+		tg_pt_gp->tg_pt_gp_alua_access_type = TPGS_EXPLICIT_ALUA;
 	else if (tmp == 1)
-		tg_pt_gp->tg_pt_gp_alua_access_type = TPGS_IMPLICT_ALUA;
+		tg_pt_gp->tg_pt_gp_alua_access_type = TPGS_IMPLICIT_ALUA;
 	else
 		tg_pt_gp->tg_pt_gp_alua_access_type = 0;
 
@@ -1844,14 +1844,14 @@ ssize_t core_alua_store_trans_delay_msecs(
 	return count;
 }
 
-ssize_t core_alua_show_implict_trans_secs(
+ssize_t core_alua_show_implicit_trans_secs(
 	struct t10_alua_tg_pt_gp *tg_pt_gp,
 	char *page)
 {
-	return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_implict_trans_secs);
+	return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_implicit_trans_secs);
 }
 
-ssize_t core_alua_store_implict_trans_secs(
+ssize_t core_alua_store_implicit_trans_secs(
 	struct t10_alua_tg_pt_gp *tg_pt_gp,
 	const char *page,
 	size_t count)
@@ -1861,16 +1861,16 @@ ssize_t core_alua_store_implict_trans_secs(
 
 	ret = kstrtoul(page, 0, &tmp);
 	if (ret < 0) {
-		pr_err("Unable to extract implict_trans_secs\n");
+		pr_err("Unable to extract implicit_trans_secs\n");
 		return ret;
 	}
-	if (tmp > ALUA_MAX_IMPLICT_TRANS_SECS) {
-		pr_err("Passed implict_trans_secs: %lu, exceeds"
-			" ALUA_MAX_IMPLICT_TRANS_SECS: %d\n", tmp,
-			ALUA_MAX_IMPLICT_TRANS_SECS);
+	if (tmp > ALUA_MAX_IMPLICIT_TRANS_SECS) {
+		pr_err("Passed implicit_trans_secs: %lu, exceeds"
+			" ALUA_MAX_IMPLICIT_TRANS_SECS: %d\n", tmp,
+			ALUA_MAX_IMPLICIT_TRANS_SECS);
 		return  -EINVAL;
 	}
-	tg_pt_gp->tg_pt_gp_implict_trans_secs = (int)tmp;
+	tg_pt_gp->tg_pt_gp_implicit_trans_secs = (int)tmp;
 
 	return count;
 }
@@ -1970,8 +1970,8 @@ ssize_t core_alua_store_secondary_status(
 		return ret;
 	}
 	if ((tmp != ALUA_STATUS_NONE) &&
-	    (tmp != ALUA_STATUS_ALTERED_BY_EXPLICT_STPG) &&
-	    (tmp != ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA)) {
+	    (tmp != ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG) &&
+	    (tmp != ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA)) {
 		pr_err("Illegal value for alua_tg_pt_status: %lu\n",
 				tmp);
 		return -EINVAL;
drivers/target/target_core_alua.h +10 -10
index e539c3e..74cf0c0 100644
@@ -7,8 +7,8 @@
  * from spc4r17 section 6.4.2 Table 135
  */
 #define TPGS_NO_ALUA				0x00
-#define TPGS_IMPLICT_ALUA			0x10
-#define TPGS_EXPLICT_ALUA			0x20
+#define TPGS_IMPLICIT_ALUA			0x10
+#define TPGS_EXPLICIT_ALUA			0x20
 
 /*
  * ASYMMETRIC ACCESS STATE field
@@ -28,8 +28,8 @@
  * from spc4r17 section 6.27 Table 246
  */
 #define ALUA_STATUS_NONE				0x00
-#define ALUA_STATUS_ALTERED_BY_EXPLICT_STPG		0x01
-#define ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA		0x02
+#define ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG		0x01
+#define ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA		0x02
 
 /*
  * From spc4r17, Table D.1: ASC and ASCQ Assignement
@@ -46,17 +46,17 @@
 #define ALUA_DEFAULT_NONOP_DELAY_MSECS			100
 #define ALUA_MAX_NONOP_DELAY_MSECS			10000 /* 10 seconds */
 /*
- * Used for implict and explict ALUA transitional delay, that is disabled
+ * Used for implicit and explicit ALUA transitional delay, that is disabled
  * by default, and is intended to be used for debugging client side ALUA code.
  */
 #define ALUA_DEFAULT_TRANS_DELAY_MSECS			0
 #define ALUA_MAX_TRANS_DELAY_MSECS			30000 /* 30 seconds */
 /*
- * Used for the recommended application client implict transition timeout
+ * Used for the recommended application client implicit transition timeout
  * in seconds, returned by the REPORT_TARGET_PORT_GROUPS w/ extended header.
  */
-#define ALUA_DEFAULT_IMPLICT_TRANS_SECS			0
-#define ALUA_MAX_IMPLICT_TRANS_SECS			255
+#define ALUA_DEFAULT_IMPLICIT_TRANS_SECS			0
+#define ALUA_MAX_IMPLICIT_TRANS_SECS			255
 /*
  * Used by core_alua_update_tpg_primary_metadata() and
  * core_alua_update_tpg_secondary_metadata()
@@ -113,9 +113,9 @@ extern ssize_t core_alua_show_trans_delay_msecs(struct t10_alua_tg_pt_gp *,
 					char *);
 extern ssize_t core_alua_store_trans_delay_msecs(struct t10_alua_tg_pt_gp *,
 					const char *, size_t);
-extern ssize_t core_alua_show_implict_trans_secs(struct t10_alua_tg_pt_gp *,
+extern ssize_t core_alua_show_implicit_trans_secs(struct t10_alua_tg_pt_gp *,
 					char *);
-extern ssize_t core_alua_store_implict_trans_secs(struct t10_alua_tg_pt_gp *,
+extern ssize_t core_alua_store_implicit_trans_secs(struct t10_alua_tg_pt_gp *,
 					const char *, size_t);
 extern ssize_t core_alua_show_preferred_bit(struct t10_alua_tg_pt_gp *,
 					char *);
drivers/target/target_core_configfs.c +13 -13
index b04edc1..3a964fb 100644
@@ -2036,7 +2036,7 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state(
 	int new_state, ret;
 
 	if (!tg_pt_gp->tg_pt_gp_valid_id) {
-		pr_err("Unable to do implict ALUA on non valid"
+		pr_err("Unable to do implicit ALUA on non valid"
 			" tg_pt_gp ID: %hu\n", tg_pt_gp->tg_pt_gp_valid_id);
 		return -EINVAL;
 	}
@@ -2049,9 +2049,9 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state(
 	}
 	new_state = (int)tmp;
 
-	if (!(tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICT_ALUA)) {
-		pr_err("Unable to process implict configfs ALUA"
-			" transition while TPGS_IMPLICT_ALUA is disabled\n");
+	if (!(tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICIT_ALUA)) {
+		pr_err("Unable to process implicit configfs ALUA"
+			" transition while TPGS_IMPLICIT_ALUA is disabled\n");
 		return -EINVAL;
 	}
 
@@ -2097,8 +2097,8 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_status(
 	new_status = (int)tmp;
 
 	if ((new_status != ALUA_STATUS_NONE) &&
-	    (new_status != ALUA_STATUS_ALTERED_BY_EXPLICT_STPG) &&
-	    (new_status != ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA)) {
+	    (new_status != ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG) &&
+	    (new_status != ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA)) {
 		pr_err("Illegal ALUA access status: 0x%02x\n",
 				new_status);
 		return -EINVAL;
@@ -2210,24 +2210,24 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_trans_delay_msecs(
 SE_DEV_ALUA_TG_PT_ATTR(trans_delay_msecs, S_IRUGO | S_IWUSR);
 
 /*
- * implict_trans_secs
+ * implicit_trans_secs
  */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_implict_trans_secs(
+static ssize_t target_core_alua_tg_pt_gp_show_attr_implicit_trans_secs(
 	struct t10_alua_tg_pt_gp *tg_pt_gp,
 	char *page)
 {
-	return core_alua_show_implict_trans_secs(tg_pt_gp, page);
+	return core_alua_show_implicit_trans_secs(tg_pt_gp, page);
 }
 
-static ssize_t target_core_alua_tg_pt_gp_store_attr_implict_trans_secs(
+static ssize_t target_core_alua_tg_pt_gp_store_attr_implicit_trans_secs(
 	struct t10_alua_tg_pt_gp *tg_pt_gp,
 	const char *page,
 	size_t count)
 {
-	return core_alua_store_implict_trans_secs(tg_pt_gp, page, count);
+	return core_alua_store_implicit_trans_secs(tg_pt_gp, page, count);
 }
 
-SE_DEV_ALUA_TG_PT_ATTR(implict_trans_secs, S_IRUGO | S_IWUSR);
+SE_DEV_ALUA_TG_PT_ATTR(implicit_trans_secs, S_IRUGO | S_IWUSR);
 
 /*
  * preferred
@@ -2353,7 +2353,7 @@ static struct configfs_attribute *target_core_alua_tg_pt_gp_attrs[] = {
 	&target_core_alua_tg_pt_gp_alua_write_metadata.attr,
 	&target_core_alua_tg_pt_gp_nonop_delay_msecs.attr,
 	&target_core_alua_tg_pt_gp_trans_delay_msecs.attr,
-	&target_core_alua_tg_pt_gp_implict_trans_secs.attr,
+	&target_core_alua_tg_pt_gp_implicit_trans_secs.attr,
 	&target_core_alua_tg_pt_gp_preferred.attr,
 	&target_core_alua_tg_pt_gp_tg_pt_gp_id.attr,
 	&target_core_alua_tg_pt_gp_members.attr,
drivers/target/target_core_device.c +3 -3
index 986afd2..207b340 100644
@@ -313,14 +313,14 @@ int core_enable_device_list_for_node(
 	deve = nacl->device_list[mapped_lun];
 
 	/*
-	 * Check if the call is handling demo mode -> explict LUN ACL
+	 * Check if the call is handling demo mode -> explicit LUN ACL
 	 * transition.  This transition must be for the same struct se_lun
 	 * + mapped_lun that was setup in demo mode..
 	 */
 	if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) {
 		if (deve->se_lun_acl != NULL) {
 			pr_err("struct se_dev_entry->se_lun_acl"
-			       " already set for demo mode -> explict"
+			       " already set for demo mode -> explicit"
 			       " LUN ACL transition\n");
 			spin_unlock_irq(&nacl->device_list_lock);
 			return -EINVAL;
@@ -328,7 +328,7 @@ int core_enable_device_list_for_node(
 		if (deve->se_lun != lun) {
 			pr_err("struct se_dev_entry->se_lun does"
 			       " match passed struct se_lun for demo mode"
-			       " -> explict LUN ACL transition\n");
+			       " -> explicit LUN ACL transition\n");
 			spin_unlock_irq(&nacl->device_list_lock);
 			return -EINVAL;
 		}
drivers/target/target_core_file.c +1 -1
index b662f89..0e34cda 100644
@@ -562,7 +562,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
 	} else {
 		ret = fd_do_rw(cmd, sgl, sgl_nents, 1);
 		/*
-		 * Perform implict vfs_fsync_range() for fd_do_writev() ops
+		 * Perform implicit vfs_fsync_range() for fd_do_writev() ops
 		 * for SCSI WRITEs with Forced Unit Access (FUA) set.
 		 * Allow this to happen independent of WCE=0 setting.
 		 */
drivers/target/target_core_pr.c +12 -12
index d1ae4c5..2f5d779 100644
@@ -474,7 +474,7 @@ static int core_scsi3_pr_seq_non_holder(
 	 * statement.
 	 */
 	if (!ret && !other_cdb) {
-		pr_debug("Allowing explict CDB: 0x%02x for %s"
+		pr_debug("Allowing explicit CDB: 0x%02x for %s"
 			" reservation holder\n", cdb[0],
 			core_scsi3_pr_dump_type(pr_reg_type));
 
@@ -507,7 +507,7 @@ static int core_scsi3_pr_seq_non_holder(
 			 */
 
 			if (!registered_nexus) {
-				pr_debug("Allowing implict CDB: 0x%02x"
+				pr_debug("Allowing implicit CDB: 0x%02x"
 					" for %s reservation on unregistered"
 					" nexus\n", cdb[0],
 					core_scsi3_pr_dump_type(pr_reg_type));
@@ -522,7 +522,7 @@ static int core_scsi3_pr_seq_non_holder(
 			 * allow commands from registered nexuses.
 			 */
 
-			pr_debug("Allowing implict CDB: 0x%02x for %s"
+			pr_debug("Allowing implicit CDB: 0x%02x for %s"
 				" reservation\n", cdb[0],
 				core_scsi3_pr_dump_type(pr_reg_type));
 
@@ -683,7 +683,7 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
 					alua_port_list) {
 			/*
 			 * This pointer will be NULL for demo mode MappedLUNs
-			 * that have not been make explict via a ConfigFS
+			 * that have not been make explicit via a ConfigFS
 			 * MappedLUN group for the SCSI Initiator Node ACL.
 			 */
 			if (!deve_tmp->se_lun_acl)
@@ -1158,7 +1158,7 @@ static void core_scsi3_put_pr_reg(struct t10_pr_registration *pr_reg)
 	smp_mb__after_atomic_dec();
 }
 
-static int core_scsi3_check_implict_release(
+static int core_scsi3_check_implicit_release(
 	struct se_device *dev,
 	struct t10_pr_registration *pr_reg)
 {
@@ -1174,7 +1174,7 @@ static int core_scsi3_check_implict_release(
 	}
 	if (pr_res_holder == pr_reg) {
 		/*
-		 * Perform an implict RELEASE if the registration that
+		 * Perform an implicit RELEASE if the registration that
 		 * is being released is holding the reservation.
 		 *
 		 * From spc4r17, section 5.7.11.1:
@@ -1192,7 +1192,7 @@ static int core_scsi3_check_implict_release(
 		 * For 'All Registrants' reservation types, all existing
 		 * registrations are still processed as reservation holders
 		 * in core_scsi3_pr_seq_non_holder() after the initial
-		 * reservation holder is implictly released here.
+		 * reservation holder is implicitly released here.
 		 */
 	} else if (pr_reg->pr_reg_all_tg_pt &&
 		  (!strcmp(pr_res_holder->pr_reg_nacl->initiatorname,
@@ -2125,7 +2125,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
 		/*
 		 * sa_res_key=0 Unregister Reservation Key for registered I_T Nexus.
 		 */
-		pr_holder = core_scsi3_check_implict_release(
+		pr_holder = core_scsi3_check_implicit_release(
 				cmd->se_dev, pr_reg);
 		if (pr_holder < 0) {
 			ret = TCM_RESERVATION_CONFLICT;
@@ -2402,7 +2402,7 @@ static void __core_scsi3_complete_pro_release(
 	struct se_device *dev,
 	struct se_node_acl *se_nacl,
 	struct t10_pr_registration *pr_reg,
-	int explict)
+	int explicit)
 {
 	struct target_core_fabric_ops *tfo = se_nacl->se_tpg->se_tpg_tfo;
 	char i_buf[PR_REG_ISID_ID_LEN];
@@ -2416,7 +2416,7 @@ static void __core_scsi3_complete_pro_release(
 
 	pr_debug("SPC-3 PR [%s] Service Action: %s RELEASE cleared"
 		" reservation holder TYPE: %s ALL_TG_PT: %d\n",
-		tfo->get_fabric_name(), (explict) ? "explict" : "implict",
+		tfo->get_fabric_name(), (explicit) ? "explicit" : "implicit",
 		core_scsi3_pr_dump_type(pr_reg->pr_res_type),
 		(pr_reg->pr_reg_all_tg_pt) ? 1 : 0);
 	pr_debug("SPC-3 PR [%s] RELEASE Node: %s%s\n",
@@ -2692,7 +2692,7 @@ static void __core_scsi3_complete_pro_preempt(
 	memset(i_buf, 0, PR_REG_ISID_ID_LEN);
 	core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
 	/*
-	 * Do an implict RELEASE of the existing reservation.
+	 * Do an implicit RELEASE of the existing reservation.
 	 */
 	if (dev->dev_pr_res_holder)
 		__core_scsi3_complete_pro_release(dev, nacl,
@@ -2845,7 +2845,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
 				 * 5.7.11.4 Preempting, Table 52 and Figure 7.
 				 *
 				 * For a ZERO SA Reservation key, release
-				 * all other registrations and do an implict
+				 * all other registrations and do an implicit
 				 * release of active persistent reservation.
 				 *
 				 * For a non-ZERO SA Reservation key, only
drivers/target/target_core_spc.c +3 -3
index f89a86f..021c3f4 100644
@@ -48,7 +48,7 @@ static void spc_fill_alua_data(struct se_port *port, unsigned char *buf)
 	buf[5]	= 0x80;
 
 	/*
-	 * Set TPGS field for explict and/or implict ALUA access type
+	 * Set TPGS field for explicit and/or implicit ALUA access type
 	 * and opteration.
 	 *
 	 * See spc4r17 section 6.4.2 Table 135
@@ -1257,7 +1257,7 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
 		*size = (cdb[3] << 8) + cdb[4];
 
 		/*
-		 * Do implict HEAD_OF_QUEUE processing for INQUIRY.
+		 * Do implicit HEAD_OF_QUEUE processing for INQUIRY.
 		 * See spc4r17 section 5.3
 		 */
 		cmd->sam_task_attr = MSG_HEAD_TAG;
@@ -1291,7 +1291,7 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
 		cmd->execute_cmd = spc_emulate_report_luns;
 		*size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
 		/*
-		 * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS
+		 * Do implicit HEAD_OF_QUEUE processing for REPORT_LUNS
 		 * See spc4r17 section 5.3
 		 */
 		cmd->sam_task_attr = MSG_HEAD_TAG;
drivers/target/target_core_transport.c +2 -2
index 46d8229..269a798 100644
@@ -462,7 +462,7 @@ void transport_deregister_session(struct se_session *se_sess)
 	pr_debug("TARGET_CORE[%s]: Deregistered fabric_sess\n",
 		se_tpg->se_tpg_tfo->get_fabric_name());
 	/*
-	 * If last kref is dropping now for an explict NodeACL, awake sleeping
+	 * If last kref is dropping now for an explicit NodeACL, awake sleeping
 	 * ->acl_free_comp caller to wakeup configfs se_node_acl->acl_group
 	 * removal context.
 	 */
@@ -636,7 +636,7 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
 		cmd->transport_state |= CMD_T_FAILED;
 
 	/*
-	 * Check for case where an explict ABORT_TASK has been received
+	 * Check for case where an explicit ABORT_TASK has been received
 	 * and transport_wait_for_tasks() will be waiting for completion..
 	 */
 	if (cmd->transport_state & CMD_T_ABORTED &&
drivers/target/target_core_ua.h +1 -1
index 0204952..be912b3 100644
@@ -19,7 +19,7 @@
 #define ASCQ_2AH_RESERVATIONS_RELEASED				0x04
 #define ASCQ_2AH_REGISTRATIONS_PREEMPTED			0x05
 #define ASCQ_2AH_ASYMMETRIC_ACCESS_STATE_CHANGED		0x06
-#define ASCQ_2AH_IMPLICT_ASYMMETRIC_ACCESS_STATE_TRANSITION_FAILED 0x07
+#define ASCQ_2AH_IMPLICIT_ASYMMETRIC_ACCESS_STATE_TRANSITION_FAILED 0x07
 #define ASCQ_2AH_PRIORITY_CHANGED				0x08
 
 #define ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS		0x09
include/target/target_core_base.h +1 -1
index 499e85d..658b356 100644
@@ -287,7 +287,7 @@ struct t10_alua_tg_pt_gp {
 	int	tg_pt_gp_alua_access_type;
 	int	tg_pt_gp_nonop_delay_msecs;
 	int	tg_pt_gp_trans_delay_msecs;
-	int	tg_pt_gp_implict_trans_secs;
+	int	tg_pt_gp_implicit_trans_secs;
 	int	tg_pt_gp_pref;
 	int	tg_pt_gp_write_metadata;
 	/* Used by struct t10_alua_tg_pt_gp->tg_pt_gp_md_buf_len */
Signature · 1 line
1.7.12.4
#2 lore raw

Re: [PATCH 01/18] target core: rename (ex,im)plict -> (ex,im)plicit

Quoted 13 lines · Hannes Reinecke
---
 drivers/target/target_core_alua.c      | 110 ++++++++++++++++-----------------
 drivers/target/target_core_alua.h      |  20 +++---
 drivers/target/target_core_configfs.c  |  26 ++++----
 drivers/target/target_core_device.c    |   6 +-
 drivers/target/target_core_file.c      |   2 +-
 drivers/target/target_core_pr.c        |  24 +++----
 drivers/target/target_core_spc.c       |   6 +-
 drivers/target/target_core_transport.c |   4 +-
 drivers/target/target_core_ua.h        |   2 +-
 include/target/target_core_base.h      |   2 +-
 10 files changed, 101 insertions(+), 101 deletions(-)

Applied. Thanks Hannes!

--nab

#3 lore raw

PATCH v2 2/18 target_core_alua: spellcheck

In reply to Hannes Reinecke
---
 drivers/target/target_core_alua.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)
drivers/target/target_core_alua.c +9 -9
index 8297d37..1994353 100644
@@ -330,7 +330,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
 			spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 		} else {
 			/*
-			 * Extact the RELATIVE TARGET PORT IDENTIFIER to identify
+			 * Extract the RELATIVE TARGET PORT IDENTIFIER to identify
 			 * the Target Port in question for the the incoming
 			 * SET_TARGET_PORT_GROUPS op.
 			 */
@@ -487,7 +487,7 @@ static inline int core_alua_state_transition(
 	u8 *alua_ascq)
 {
 	/*
-	 * Allowed CDBs for ALUA_ACCESS_STATE_TRANSITIO as defined by
+	 * Allowed CDBs for ALUA_ACCESS_STATE_TRANSITION as defined by
 	 * spc4r17 section 5.9.2.5
 	 */
 	switch (cdb[0]) {
@@ -515,9 +515,9 @@ static inline int core_alua_state_transition(
 }
 
 /*
- * return 1: Is used to signal LUN not accecsable, and check condition/not ready
+ * return 1: Is used to signal LUN not accessible, and check condition/not ready
  * return 0: Used to signal success
- * reutrn -1: Used to signal failure, and invalid cdb field
+ * return -1: Used to signal failure, and invalid cdb field
  */
 sense_reason_t
 target_alua_state_check(struct se_cmd *cmd)
@@ -802,7 +802,7 @@ static int core_alua_do_transition_tg_pt(
 		 * change, a device server shall establish a unit attention
 		 * condition for the initiator port associated with every I_T
 		 * nexus with the additional sense code set to ASYMMETRIC
-		 * ACCESS STATE CHAGED.
+		 * ACCESS STATE CHANGED.
 		 *
 		 * After an explicit target port asymmetric access state
 		 * change, a device server shall establish a unit attention
@@ -946,7 +946,7 @@ int core_alua_do_port_transition(
 				continue;
 			/*
 			 * If the target behavior port asymmetric access state
-			 * is changed for any target port group accessiable via
+			 * is changed for any target port group accessible via
 			 * a logical unit within a LU group, the target port
 			 * behavior group asymmetric access states for the same
 			 * target port group accessible via other logical units
@@ -1232,7 +1232,7 @@ void core_alua_free_lu_gp(struct t10_alua_lu_gp *lu_gp)
 		 * struct se_device is released via core_alua_free_lu_gp_mem().
 		 *
 		 * If the passed lu_gp does NOT match the default_lu_gp, assume
-		 * we want to re-assocate a given lu_gp_mem with default_lu_gp.
+		 * we want to re-associate a given lu_gp_mem with default_lu_gp.
 		 */
 		spin_lock(&lu_gp_mem->lu_gp_mem_lock);
 		if (lu_gp != default_lu_gp)
@@ -1465,7 +1465,7 @@ void core_alua_free_tg_pt_gp(
 	 * been called from target_core_alua_drop_tg_pt_gp().
 	 *
 	 * Here we remove *tg_pt_gp from the global list so that
-	 * no assications *OR* explicit ALUA via SET_TARGET_PORT_GROUPS
+	 * no associations *OR* explicit ALUA via SET_TARGET_PORT_GROUPS
 	 * can be made while we are releasing struct t10_alua_tg_pt_gp.
 	 */
 	spin_lock(&dev->t10_alua.tg_pt_gps_lock);
@@ -1501,7 +1501,7 @@ void core_alua_free_tg_pt_gp(
 		 * core_alua_free_tg_pt_gp_mem().
 		 *
 		 * If the passed tg_pt_gp does NOT match the default_tg_pt_gp,
-		 * assume we want to re-assocate a given tg_pt_gp_mem with
+		 * assume we want to re-associate a given tg_pt_gp_mem with
 		 * default_tg_pt_gp.
 		 */
 		spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
Signature · 1 line
1.7.12.4
#5 lore raw

PATCH v2 3/18 target_core_alua: Rename ALUA_ACCESS_STATE_OPTIMIZED

In reply to Hannes Reinecke

Rename ALUA_ACCESS_STATE_OPTMIZED to
ALUA_ACCESS_STATE_OPTIMIZED.

---
 drivers/target/target_core_alua.c | 10 +++++-----
 drivers/target/target_core_alua.h |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)
drivers/target/target_core_alua.c +5 -5
index 1994353..08e41e3 100644
@@ -566,12 +566,12 @@ target_alua_state_check(struct se_cmd *cmd)
 	nonop_delay_msecs = tg_pt_gp->tg_pt_gp_nonop_delay_msecs;
 	spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 	/*
-	 * Process ALUA_ACCESS_STATE_ACTIVE_OPTMIZED in a separate conditional
+	 * Process ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED in a separate conditional
 	 * statement so the compiler knows explicitly to check this case first.
 	 * For the Optimized ALUA access state case, we want to process the
 	 * incoming fabric cmd ASAP..
 	 */
-	if (out_alua_state == ALUA_ACCESS_STATE_ACTIVE_OPTMIZED)
+	if (out_alua_state == ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED)
 		return 0;
 
 	switch (out_alua_state) {
@@ -626,7 +626,7 @@ static sense_reason_t
 core_alua_check_transition(int state, int *primary)
 {
 	switch (state) {
-	case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED:
+	case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED:
 	case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
 	case ALUA_ACCESS_STATE_STANDBY:
 	case ALUA_ACCESS_STATE_UNAVAILABLE:
@@ -654,7 +654,7 @@ core_alua_check_transition(int state, int *primary)
 static char *core_alua_dump_state(int state)
 {
 	switch (state) {
-	case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED:
+	case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED:
 		return "Active/Optimized";
 	case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
 		return "Active/NonOptimized";
@@ -1354,7 +1354,7 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev,
 	tg_pt_gp->tg_pt_gp_dev = dev;
 	tg_pt_gp->tg_pt_gp_md_buf_len = ALUA_MD_BUF_LEN;
 	atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
-		ALUA_ACCESS_STATE_ACTIVE_OPTMIZED);
+		ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED);
 	/*
 	 * Enable both explicit and implicit ALUA support by default
 	 */
drivers/target/target_core_alua.h +1 -1
index 74cf0c0..d6db78b 100644
@@ -15,7 +15,7 @@
  *
  * from spc4r17 section 6.27 Table 245
  */
-#define ALUA_ACCESS_STATE_ACTIVE_OPTMIZED	0x0
+#define ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED	0x0
 #define ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED	0x1
 #define ALUA_ACCESS_STATE_STANDBY		0x2
 #define ALUA_ACCESS_STATE_UNAVAILABLE		0x3
Signature · 1 line
1.7.12.4
#6 lore raw

Re: [PATCH 03/18] target_core_alua: Rename ALUA_ACCESS_STATE_OPTIMIZED

Quoted 3 lines · Hannes Reinecke

Rename ALUA_ACCESS_STATE_OPTMIZED to
ALUA_ACCESS_STATE_OPTIMIZED.

Applied.

--nab

#7 lore raw

PATCH v2 4/18 target_core_alua: Store supported ALUA states

In reply to Hannes Reinecke

The supported ALUA states might be different for individual devices, so store it in a separate field.

---
 drivers/target/target_core_alua.c | 14 ++++++++------
 drivers/target/target_core_alua.h | 11 +++++++++++
 include/target/target_core_base.h |  1 +
 3 files changed, 20 insertions(+), 6 deletions(-)
drivers/target/target_core_alua.c +8 -6
index 08e41e3..a16115e 100644
@@ -117,12 +117,7 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd)
 		/*
 		 * Set supported ASYMMETRIC ACCESS State bits
 		 */
-		buf[off] = 0x80; /* T_SUP */
-		buf[off] |= 0x40; /* O_SUP */
-		buf[off] |= 0x8; /* U_SUP */
-		buf[off] |= 0x4; /* S_SUP */
-		buf[off] |= 0x2; /* AN_SUP */
-		buf[off++] |= 0x1; /* AO_SUP */
+		buf[off++] |= tg_pt_gp->tg_pt_gp_alua_supported_states;
 		/*
 		 * TARGET PORT GROUP
 		 */
@@ -1367,6 +1362,13 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev,
 	tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS;
 	tg_pt_gp->tg_pt_gp_implicit_trans_secs = ALUA_DEFAULT_IMPLICIT_TRANS_SECS;
 
+	/*
+	 * Enable all supported states
+	 */
+	tg_pt_gp->tg_pt_gp_alua_supported_states =
+	    ALUA_T_SUP | ALUA_O_SUP | \
+	    ALUA_U_SUP | ALUA_S_SUP | ALUA_AN_SUP | ALUA_AO_SUP;
+
 	if (def_group) {
 		spin_lock(&dev->t10_alua.tg_pt_gps_lock);
 		tg_pt_gp->tg_pt_gp_id =
drivers/target/target_core_alua.h +11 -0
index d6db78b..88e2e83 100644
@@ -23,6 +23,17 @@
 #define ALUA_ACCESS_STATE_TRANSITION		0xf
 
 /*
+ * from spc4r36j section 6.37 Table 306
+ */
+#define ALUA_T_SUP		0x80
+#define ALUA_O_SUP		0x40
+#define ALUA_LBD_SUP		0x10
+#define ALUA_U_SUP		0x08
+#define ALUA_S_SUP		0x04
+#define ALUA_AN_SUP		0x02
+#define ALUA_AO_SUP		0x01
+
+/*
  * REPORT_TARGET_PORT_GROUP STATUS CODE
  *
  * from spc4r17 section 6.27 Table 246
include/target/target_core_base.h +1 -0
index 658b356..a23785f 100644
@@ -283,6 +283,7 @@ struct t10_alua_lu_gp_member {
 struct t10_alua_tg_pt_gp {
 	u16	tg_pt_gp_id;
 	int	tg_pt_gp_valid_id;
+	int	tg_pt_gp_alua_supported_states;
 	int	tg_pt_gp_alua_access_status;
 	int	tg_pt_gp_alua_access_type;
 	int	tg_pt_gp_nonop_delay_msecs;
Signature · 1 line
1.7.12.4
#8 lore raw

Re: [PATCH 04/18] target_core_alua: Store supported ALUA states

Quoted 4 lines · Hannes Reinecke

The supported ALUA states might be different for individual devices, so store it in a separate field.

Applied, with one minor change below..

Quoted 25 lines
---
 drivers/target/target_core_alua.c | 14 ++++++++------
 drivers/target/target_core_alua.h | 11 +++++++++++
 include/target/target_core_base.h |  1 +
 3 files changed, 20 insertions(+), 6 deletions(-)
drivers/target/target_core_alua.c +1 -6
index 08e41e3..a16115e 100644
@@ -117,12 +117,7 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd)
 		/*
 		 * Set supported ASYMMETRIC ACCESS State bits
 		 */
-		buf[off] = 0x80; /* T_SUP */
-		buf[off] |= 0x40; /* O_SUP */
-		buf[off] |= 0x8; /* U_SUP */
-		buf[off] |= 0x4; /* S_SUP */
-		buf[off] |= 0x2; /* AN_SUP */
-		buf[off++] |= 0x1; /* AO_SUP */
+		buf[off++] |= tg_pt_gp->tg_pt_gp_alua_supported_states;
 		/*
 		 * TARGET PORT GROUP
 		 */

drivers/target/target_core_alua.c struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev, · line 1371

Quoted 10 lines
drivers/target/target_core_alua.c +7 -0
@@ -1367,6 +1362,13 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev,
 	tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS;
 	tg_pt_gp->tg_pt_gp_implicit_trans_secs = ALUA_DEFAULT_IMPLICIT_TRANS_SECS;
 
+	/*
+	 * Enable all supported states
+	 */
+	tg_pt_gp->tg_pt_gp_alua_supported_states =
+	    ALUA_T_SUP | ALUA_O_SUP | \
+	    ALUA_U_SUP | ALUA_S_SUP | ALUA_AN_SUP | ALUA_AO_SUP;
+

Dropping the unnecessary line continuation here..

--nab

#9 lore raw

PATCH v2 5/18 target_core_alua: Make supported states configurable

In reply to Hannes Reinecke
---
 drivers/target/target_core_configfs.c | 50 +++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)
drivers/target/target_core_configfs.c +50 -0
index 3a964fb..1e4ea28 100644
@@ -2131,6 +2131,55 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_type(
 SE_DEV_ALUA_TG_PT_ATTR(alua_access_type, S_IRUGO | S_IWUSR);
 
 /*
+ * alua_supported_states
+ */
+static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_supported_states(
+	struct t10_alua_tg_pt_gp *tg_pt_gp,
+	char *page)
+{
+	return sprintf(page, "%02x\n",
+		tg_pt_gp->tg_pt_gp_alua_supported_states);
+}
+
+static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_supported_states(
+	struct t10_alua_tg_pt_gp *tg_pt_gp,
+	const char *page,
+	size_t count)
+{
+	unsigned long tmp;
+	int new_states, valid_states, ret;
+
+	if (!tg_pt_gp->tg_pt_gp_valid_id) {
+		pr_err("Unable to do set supported ALUA states on non"
+			" valid tg_pt_gp ID: %hu\n",
+			tg_pt_gp->tg_pt_gp_valid_id);
+		return -EINVAL;
+	}
+
+	ret = strict_strtoul(page, 0, &tmp);
+	if (ret < 0) {
+		pr_err("Unable to extract new supported ALUA states"
+				" from %s\n", page);
+		return -EINVAL;
+	}
+	new_states = (int)tmp;
+	valid_states = ALUA_T_SUP | ALUA_O_SUP | ALUA_LBD_SUP | \
+	    ALUA_U_SUP | ALUA_S_SUP | ALUA_AN_SUP | ALUA_AO_SUP;
+
+
+	if (new_states & ~valid_states) {
+		pr_err("Illegal supported ALUA states: 0x%02x\n",
+				new_states);
+		return -EINVAL;
+	}
+
+	tg_pt_gp->tg_pt_gp_alua_supported_states = new_states;
+	return count;
+}
+
+SE_DEV_ALUA_TG_PT_ATTR(alua_supported_states, S_IRUGO | S_IWUSR);
+
+/*
  * alua_write_metadata
  */
 static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_write_metadata(
@@ -2350,6 +2399,7 @@ static struct configfs_attribute *target_core_alua_tg_pt_gp_attrs[] = {
 	&target_core_alua_tg_pt_gp_alua_access_state.attr,
 	&target_core_alua_tg_pt_gp_alua_access_status.attr,
 	&target_core_alua_tg_pt_gp_alua_access_type.attr,
+	&target_core_alua_tg_pt_gp_alua_supported_states.attr,
 	&target_core_alua_tg_pt_gp_alua_write_metadata.attr,
 	&target_core_alua_tg_pt_gp_nonop_delay_msecs.attr,
 	&target_core_alua_tg_pt_gp_trans_delay_msecs.attr,
Signature · 1 line
1.7.12.4
#10 lore raw

Re: [PATCH 05/18] target_core_alua: Make supported states configurable

Quoted 2 lines · Hannes Reinecke

---

Applied, with two minor changes below..

Quoted 32 lines
 drivers/target/target_core_configfs.c | 50 +++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)
drivers/target/target_core_configfs.c +21 -0
index 3a964fb..1e4ea28 100644
@@ -2131,6 +2131,55 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_type(
 SE_DEV_ALUA_TG_PT_ATTR(alua_access_type, S_IRUGO | S_IWUSR);
 
 /*
+ * alua_supported_states
+ */
+static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_supported_states(
+	struct t10_alua_tg_pt_gp *tg_pt_gp,
+	char *page)
+{
+	return sprintf(page, "%02x\n",
+		tg_pt_gp->tg_pt_gp_alua_supported_states);
+}
+
+static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_supported_states(
+	struct t10_alua_tg_pt_gp *tg_pt_gp,
+	const char *page,
+	size_t count)
+{
+	unsigned long tmp;
+	int new_states, valid_states, ret;
+
+	if (!tg_pt_gp->tg_pt_gp_valid_id) {
+		pr_err("Unable to do set supported ALUA states on non"
+			" valid tg_pt_gp ID: %hu\n",

drivers/target/target_core_configfs.c static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_type( · line 2164

Quoted 10 lines
drivers/target/target_core_configfs.c +10 -0
+			tg_pt_gp->tg_pt_gp_valid_id);
+		return -EINVAL;
+	}
+
+	ret = strict_strtoul(page, 0, &tmp);
+	if (ret < 0) {
+		pr_err("Unable to extract new supported ALUA states"
+				" from %s\n", page);
+		return -EINVAL;
+	}

Changed strict_strtoul() -> kstrtoul()

drivers/target/target_core_configfs.c static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_type( · line 2168

Quoted 4 lines
drivers/target/target_core_configfs.c +4 -0
+	new_states = (int)tmp;
+	valid_states = ALUA_T_SUP | ALUA_O_SUP | ALUA_LBD_SUP | \
+	    ALUA_U_SUP | ALUA_S_SUP | ALUA_AN_SUP | ALUA_AO_SUP;
+

Dropping the unnecessary line continuation here..

--nab

#11 lore raw

PATCH v2 6/18 target_core_configfs: split up ALUA supported states

In reply to Hannes Reinecke

Split up the various ALUA states into individual attributes to make parsing easier and adhere to the one value per attribute sysfs principle.

---
 drivers/target/target_core_configfs.c | 127 ++++++++++++++++++++++------------
 1 file changed, 84 insertions(+), 43 deletions(-)
drivers/target/target_core_configfs.c +84 -43
index 1e4ea28..8476f48 100644
@@ -2133,51 +2133,86 @@ SE_DEV_ALUA_TG_PT_ATTR(alua_access_type, S_IRUGO | S_IWUSR);
 /*
  * alua_supported_states
  */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_supported_states(
-	struct t10_alua_tg_pt_gp *tg_pt_gp,
-	char *page)
-{
-	return sprintf(page, "%02x\n",
-		tg_pt_gp->tg_pt_gp_alua_supported_states);
-}
-
-static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_supported_states(
-	struct t10_alua_tg_pt_gp *tg_pt_gp,
-	const char *page,
-	size_t count)
-{
-	unsigned long tmp;
-	int new_states, valid_states, ret;
 
-	if (!tg_pt_gp->tg_pt_gp_valid_id) {
-		pr_err("Unable to do set supported ALUA states on non"
-			" valid tg_pt_gp ID: %hu\n",
-			tg_pt_gp->tg_pt_gp_valid_id);
-		return -EINVAL;
-	}
-
-	ret = strict_strtoul(page, 0, &tmp);
-	if (ret < 0) {
-		pr_err("Unable to extract new supported ALUA states"
-				" from %s\n", page);
-		return -EINVAL;
-	}
-	new_states = (int)tmp;
-	valid_states = ALUA_T_SUP | ALUA_O_SUP | ALUA_LBD_SUP | \
-	    ALUA_U_SUP | ALUA_S_SUP | ALUA_AN_SUP | ALUA_AO_SUP;
-
-
-	if (new_states & ~valid_states) {
-		pr_err("Illegal supported ALUA states: 0x%02x\n",
-				new_states);
-		return -EINVAL;
-	}
-
-	tg_pt_gp->tg_pt_gp_alua_supported_states = new_states;
-	return count;
+#define SE_DEV_ALUA_SUPPORT_STATE_SHOW(_name, _var, _bit)		\
+static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_support_##_name( \
+	struct t10_alua_tg_pt_gp *t, char *p)				\
+{									\
+	return sprintf(p, "%d\n", !!(t->_var & _bit));			\
 }
 
-SE_DEV_ALUA_TG_PT_ATTR(alua_supported_states, S_IRUGO | S_IWUSR);
+#define SE_DEV_ALUA_SUPPORT_STATE_STORE(_name, _var, _bit)		\
+static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_support_##_name(\
+	struct t10_alua_tg_pt_gp *t, const char *p, size_t c)		\
+{									\
+	unsigned long tmp;						\
+	int ret;							\
+									\
+	if (!t->tg_pt_gp_valid_id) {					\
+		pr_err("Unable to do set ##_name ALUA state on non"	\
+		       " valid tg_pt_gp ID: %hu\n",			\
+		       t->tg_pt_gp_valid_id);				\
+		return -EINVAL;						\
+	}								\
+									\
+	ret = strict_strtoul(p, 0, &tmp);				\
+	if (ret < 0) {							\
+		pr_err("Invalid value '%s', must be '0' or '1'\n", p);	\
+		return -EINVAL;						\
+	}								\
+	if (tmp > 1) {							\
+		pr_err("Invalid value '%ld', must be '0' or '1'\n", tmp); \
+		return -EINVAL;						\
+	}								\
+	if (!tmp)							\
+		t->_var |= _bit;					\
+	else								\
+		t->_var &= ~_bit;					\
+									\
+	return c;							\
+}
+
+SE_DEV_ALUA_SUPPORT_STATE_SHOW(transitioning,
+			       tg_pt_gp_alua_supported_states, ALUA_T_SUP);
+SE_DEV_ALUA_SUPPORT_STATE_STORE(transitioning,
+				tg_pt_gp_alua_supported_states, ALUA_T_SUP);
+SE_DEV_ALUA_TG_PT_ATTR(alua_support_transitioning, S_IRUGO | S_IWUSR);
+
+SE_DEV_ALUA_SUPPORT_STATE_SHOW(offline,
+			       tg_pt_gp_alua_supported_states, ALUA_O_SUP);
+SE_DEV_ALUA_SUPPORT_STATE_STORE(offline,
+				tg_pt_gp_alua_supported_states, ALUA_O_SUP);
+SE_DEV_ALUA_TG_PT_ATTR(alua_support_offline, S_IRUGO | S_IWUSR);
+
+SE_DEV_ALUA_SUPPORT_STATE_SHOW(lba_dependent,
+			       tg_pt_gp_alua_supported_states, ALUA_LBD_SUP);
+SE_DEV_ALUA_SUPPORT_STATE_STORE(lba_dependent,
+				tg_pt_gp_alua_supported_states, ALUA_LBD_SUP);
+SE_DEV_ALUA_TG_PT_ATTR(alua_support_lba_dependent, S_IRUGO | S_IWUSR);
+
+SE_DEV_ALUA_SUPPORT_STATE_SHOW(unavailable,
+			       tg_pt_gp_alua_supported_states, ALUA_U_SUP);
+SE_DEV_ALUA_SUPPORT_STATE_STORE(unavailable,
+				tg_pt_gp_alua_supported_states, ALUA_U_SUP);
+SE_DEV_ALUA_TG_PT_ATTR(alua_support_unavailable, S_IRUGO | S_IWUSR);
+
+SE_DEV_ALUA_SUPPORT_STATE_SHOW(standby,
+			       tg_pt_gp_alua_supported_states, ALUA_S_SUP);
+SE_DEV_ALUA_SUPPORT_STATE_STORE(standby,
+				tg_pt_gp_alua_supported_states, ALUA_S_SUP);
+SE_DEV_ALUA_TG_PT_ATTR(alua_support_standby, S_IRUGO | S_IWUSR);
+
+SE_DEV_ALUA_SUPPORT_STATE_SHOW(active_optimized,
+			       tg_pt_gp_alua_supported_states, ALUA_AO_SUP);
+SE_DEV_ALUA_SUPPORT_STATE_STORE(active_optimized,
+				tg_pt_gp_alua_supported_states, ALUA_AO_SUP);
+SE_DEV_ALUA_TG_PT_ATTR(alua_support_active_optimized, S_IRUGO | S_IWUSR);
+
+SE_DEV_ALUA_SUPPORT_STATE_SHOW(active_nonoptimized,
+			       tg_pt_gp_alua_supported_states, ALUA_AN_SUP);
+SE_DEV_ALUA_SUPPORT_STATE_STORE(active_nonoptimized,
+				tg_pt_gp_alua_supported_states, ALUA_AN_SUP);
+SE_DEV_ALUA_TG_PT_ATTR(alua_support_active_nonoptimized, S_IRUGO | S_IWUSR);
 
 /*
  * alua_write_metadata
@@ -2399,7 +2434,13 @@ static struct configfs_attribute *target_core_alua_tg_pt_gp_attrs[] = {
 	&target_core_alua_tg_pt_gp_alua_access_state.attr,
 	&target_core_alua_tg_pt_gp_alua_access_status.attr,
 	&target_core_alua_tg_pt_gp_alua_access_type.attr,
-	&target_core_alua_tg_pt_gp_alua_supported_states.attr,
+	&target_core_alua_tg_pt_gp_alua_support_transitioning.attr,
+	&target_core_alua_tg_pt_gp_alua_support_offline.attr,
+	&target_core_alua_tg_pt_gp_alua_support_lba_dependent.attr,
+	&target_core_alua_tg_pt_gp_alua_support_unavailable.attr,
+	&target_core_alua_tg_pt_gp_alua_support_standby.attr,
+	&target_core_alua_tg_pt_gp_alua_support_active_nonoptimized.attr,
+	&target_core_alua_tg_pt_gp_alua_support_active_optimized.attr,
 	&target_core_alua_tg_pt_gp_alua_write_metadata.attr,
 	&target_core_alua_tg_pt_gp_nonop_delay_msecs.attr,
 	&target_core_alua_tg_pt_gp_trans_delay_msecs.attr,
Signature · 1 line
1.7.12.4
#12 lore raw

Re: [PATCH 06/18] target_core_configfs: split up ALUA supported states

Quoted 6 lines · Hannes Reinecke

Split up the various ALUA states into individual attributes to make parsing easier and adhere to the one value per attribute sysfs principle.

---

Applied with one minor change below..

Quoted 7 lines
 drivers/target/target_core_configfs.c | 127 ++++++++++++++++++++++------------
 1 file changed, 84 insertions(+), 43 deletions(-)
drivers/target/target_core_configfs.c +0 -0
index 1e4ea28..8476f48 100644

<SNIP>

Quoted 6 lines
drivers/target/target_core_configfs.c +5 -1
-SE_DEV_ALUA_TG_PT_ATTR(alua_supported_states, S_IRUGO | S_IWUSR);
+#define SE_DEV_ALUA_SUPPORT_STATE_STORE(_name, _var, _bit)		\
+static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_support_##_name(\
+	struct t10_alua_tg_pt_gp *t, const char *p, size_t c)		\
+{									\
+	unsigned long tmp;						\

drivers/target/target_core_configfs.c SE_DEV_ALUA_TG_PT_ATTR(alua_access_type, S_IRUGO | S_IWUSR); · line 2158

Quoted 10 lines
drivers/target/target_core_configfs.c +10 -0
+	int ret;							\
+									\
+	if (!t->tg_pt_gp_valid_id) {					\
+		pr_err("Unable to do set ##_name ALUA state on non"	\
+		       " valid tg_pt_gp ID: %hu\n",			\
+		       t->tg_pt_gp_valid_id);				\
+		return -EINVAL;						\
+	}								\
+									\
+	ret = strict_strtoul(p, 0, &tmp);				\

Converted to kstrtoul()

--nab

#13 lore raw

PATCH v2 7/18 target_core_configfs: Verbose ALUA state display

In reply to Hannes Reinecke

Instead of printing out the ALUA state number we should be using proper strings; this helps administration and reduces confusion.

---
 drivers/target/target_core_alua.c     | 18 +++++++++++++++++-
 drivers/target/target_core_alua.h     |  2 ++
 drivers/target/target_core_configfs.c | 24 ++++++++++++++----------
 3 files changed, 33 insertions(+), 11 deletions(-)
drivers/target/target_core_alua.c +17 -1
index a16115e..26e3c6d 100644
@@ -646,7 +646,7 @@ core_alua_check_transition(int state, int *primary)
 	return 0;
 }
 
-static char *core_alua_dump_state(int state)
+char *core_alua_dump_state(int state)
 {
 	switch (state) {
 	case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED:
@@ -666,6 +666,22 @@ static char *core_alua_dump_state(int state)
 	return NULL;
 }
 
+int core_alua_parse_state(const char *state)
+{
+	if (!strncasecmp(state, "Active/Optimized", 16))
+		return ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED;
+	if (!strncasecmp(state, "Active/NonOptimized", 19))
+		return ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED;
+	if (!strncasecmp(state, "Standby", 7))
+		return ALUA_ACCESS_STATE_STANDBY;
+	if (!strncasecmp(state, "Unavailable", 11))
+		return ALUA_ACCESS_STATE_UNAVAILABLE;
+	if (!strncasecmp(state, "Offline", 7))
+		return ALUA_ACCESS_STATE_OFFLINE;
+
+	return -1;
+}
+
 char *core_alua_dump_status(int status)
 {
 	switch (status) {
drivers/target/target_core_alua.h +2 -0
index 88e2e83..24ddf85 100644
@@ -89,6 +89,8 @@ extern int core_alua_check_nonop_delay(struct se_cmd *);
 extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *,
 				struct se_device *, struct se_port *,
 				struct se_node_acl *, int, int);
+extern char *core_alua_dump_state(int);
+extern int core_alua_parse_state(const char *);
 extern char *core_alua_dump_status(int);
 extern struct t10_alua_lu_gp *core_alua_allocate_lu_gp(const char *, int);
 extern int core_alua_set_lu_gp_id(struct t10_alua_lu_gp *, u16);
drivers/target/target_core_configfs.c +14 -10
index 8476f48..dcceecf 100644
@@ -2022,10 +2022,12 @@ static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_access_state(
 	struct t10_alua_tg_pt_gp *tg_pt_gp,
 	char *page)
 {
-	return sprintf(page, "%d\n",
-		atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state));
+	int state = atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state);
+
+	return sprintf(page, "%s\n", core_alua_dump_state(state));
 }
 
+
 static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state(
 	struct t10_alua_tg_pt_gp *tg_pt_gp,
 	const char *page,
@@ -2041,20 +2043,22 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state(
 		return -EINVAL;
 	}
 
-	ret = kstrtoul(page, 0, &tmp);
-	if (ret < 0) {
-		pr_err("Unable to extract new ALUA access state from"
-				" %s\n", page);
-		return ret;
-	}
-	new_state = (int)tmp;
-
 	if (!(tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICIT_ALUA)) {
 		pr_err("Unable to process implicit configfs ALUA"
 			" transition while TPGS_IMPLICIT_ALUA is disabled\n");
 		return -EINVAL;
 	}
 
+	new_state = core_alua_parse_state(page);
+	if (new_state < 0) {
+		ret = kstrtoul(page, 0, &tmp);
+		if (ret < 0) {
+			pr_err("Unable to extract new ALUA access state from"
+			       " %s\n", page);
+			return ret;
+		}
+		new_state = (int)tmp;
+	}
 	ret = core_alua_do_port_transition(tg_pt_gp, dev,
 					NULL, NULL, new_state, 0);
 	return (!ret) ? count : -EINVAL;
Signature · 1 line
1.7.12.4
#14 lore raw

PATCH v2 8/18 target_core_configfs: Split up ALUA access type

In reply to Hannes Reinecke

Instead of lumping two independent values into one attribute we should be using on attribute per value.

---
 drivers/target/target_core_alua.c     | 46 --------------------
 drivers/target/target_core_alua.h     |  3 --
 drivers/target/target_core_configfs.c | 79 +++++++++++++++++------------------
 3 files changed, 38 insertions(+), 90 deletions(-)
drivers/target/target_core_alua.c +0 -46
index 26e3c6d..c4d73a4 100644
@@ -1754,52 +1754,6 @@ ssize_t core_alua_store_tg_pt_gp_info(
 	return count;
 }
 
-ssize_t core_alua_show_access_type(
-	struct t10_alua_tg_pt_gp *tg_pt_gp,
-	char *page)
-{
-	if ((tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA) &&
-	    (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICIT_ALUA))
-		return sprintf(page, "Implicit and Explicit\n");
-	else if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICIT_ALUA)
-		return sprintf(page, "Implicit\n");
-	else if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)
-		return sprintf(page, "Explicit\n");
-	else
-		return sprintf(page, "None\n");
-}
-
-ssize_t core_alua_store_access_type(
-	struct t10_alua_tg_pt_gp *tg_pt_gp,
-	const char *page,
-	size_t count)
-{
-	unsigned long tmp;
-	int ret;
-
-	ret = kstrtoul(page, 0, &tmp);
-	if (ret < 0) {
-		pr_err("Unable to extract alua_access_type\n");
-		return ret;
-	}
-	if ((tmp != 0) && (tmp != 1) && (tmp != 2) && (tmp != 3)) {
-		pr_err("Illegal value for alua_access_type:"
-				" %lu\n", tmp);
-		return -EINVAL;
-	}
-	if (tmp == 3)
-		tg_pt_gp->tg_pt_gp_alua_access_type =
-			TPGS_IMPLICIT_ALUA | TPGS_EXPLICIT_ALUA;
-	else if (tmp == 2)
-		tg_pt_gp->tg_pt_gp_alua_access_type = TPGS_EXPLICIT_ALUA;
-	else if (tmp == 1)
-		tg_pt_gp->tg_pt_gp_alua_access_type = TPGS_IMPLICIT_ALUA;
-	else
-		tg_pt_gp->tg_pt_gp_alua_access_type = 0;
-
-	return count;
-}
-
 ssize_t core_alua_show_nonop_delay_msecs(
 	struct t10_alua_tg_pt_gp *tg_pt_gp,
 	char *page)
drivers/target/target_core_alua.h +0 -3
index 24ddf85..03955a9 100644
@@ -115,9 +115,6 @@ extern void __core_alua_attach_tg_pt_gp_mem(struct t10_alua_tg_pt_gp_member *,
 extern ssize_t core_alua_show_tg_pt_gp_info(struct se_port *, char *);
 extern ssize_t core_alua_store_tg_pt_gp_info(struct se_port *, const char *,
 						size_t);
-extern ssize_t core_alua_show_access_type(struct t10_alua_tg_pt_gp *, char *);
-extern ssize_t core_alua_store_access_type(struct t10_alua_tg_pt_gp *,
-					const char *, size_t);
 extern ssize_t core_alua_show_nonop_delay_msecs(struct t10_alua_tg_pt_gp *,
 						char *);
 extern ssize_t core_alua_store_nonop_delay_msecs(struct t10_alua_tg_pt_gp *,
drivers/target/target_core_configfs.c +38 -41

129 lines not on this page · raw message

Signature · 1 line
1.7.12.4
#15 lore raw

PATCH v2 9/18 target_core: Rename alua_access_type in alua_mgmt_type

In reply to Hannes Reinecke

'alua_access_type' is not very descriptive and leads to confusion, so rename it to 'alua_mgmt_type'.

---
 drivers/target/target_core_alua.c     | 10 +++++-----
 drivers/target/target_core_alua.h     |  6 +++---
 drivers/target/target_core_configfs.c | 32 ++++++++++++++++----------------
 drivers/target/target_core_spc.c      |  2 +-
 include/target/target_core_base.h     |  2 +-
 5 files changed, 26 insertions(+), 26 deletions(-)
drivers/target/target_core_alua.c +5 -5
index c4d73a4..5540aae 100644
@@ -246,9 +246,9 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
 	}
 	spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
 
-	if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)) {
-		pr_debug("Unable to process SET_TARGET_PORT_GROUPS"
-				" while TPGS_EXPLICIT_ALUA is disabled\n");
+	if (!(l_tg_pt_gp->tg_pt_gp_alua_mgmt_type & ALUA_MGMT_EXPLICIT)) {
+		pr_debug("Unable to process SET_TARGET_PORT_GROUPS while"
+				" explicit ALUA management is disabled\n");
 		rc = TCM_UNSUPPORTED_SCSI_OPCODE;
 		goto out;
 	}
@@ -1369,8 +1369,8 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev,
 	/*
 	 * Enable both explicit and implicit ALUA support by default
 	 */
-	tg_pt_gp->tg_pt_gp_alua_access_type =
-			TPGS_EXPLICIT_ALUA | TPGS_IMPLICIT_ALUA;
+	tg_pt_gp->tg_pt_gp_alua_mgmt_type =
+			ALUA_MGMT_EXPLICIT | ALUA_MGMT_IMPLICIT;
 	/*
 	 * Set the default Active/NonOptimized Delay in milliseconds
 	 */
drivers/target/target_core_alua.h +3 -3
index 03955a9..299dc33 100644
@@ -6,9 +6,9 @@
  *
  * from spc4r17 section 6.4.2 Table 135
  */
-#define TPGS_NO_ALUA				0x00
-#define TPGS_IMPLICIT_ALUA			0x10
-#define TPGS_EXPLICIT_ALUA			0x20
+#define ALUA_MGMT_NONE				0x00
+#define ALUA_MGMT_IMPLICIT			0x10
+#define ALUA_MGMT_EXPLICIT			0x20
 
 /*
  * ASYMMETRIC ACCESS STATE field
drivers/target/target_core_configfs.c +16 -16
index 6f01a1e..c16eb87 100644
@@ -2043,9 +2043,9 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state(
 		return -EINVAL;
 	}
 
-	if (!(tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICIT_ALUA)) {
-		pr_err("Unable to process implicit configfs ALUA"
-			" transition while TPGS_IMPLICIT_ALUA is disabled\n");
+	if (!(tg_pt_gp->tg_pt_gp_alua_mgmt_type & ALUA_MGMT_IMPLICIT)) {
+		pr_err("Unable to process implicit configfs ALUA transition"
+			" while implicit ALUA management is disabled\n");
 		return -EINVAL;
 	}
 
@@ -2153,19 +2153,19 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_##_name(	\
 }
 
 /*
- * alua_access_type
+ * alua_mgmt_type
  */
-SE_DEV_ALUA_SUPPORT_STATE_SHOW(access_implicit,
-			       tg_pt_gp_alua_access_type, TPGS_IMPLICIT_ALUA);
-SE_DEV_ALUA_SUPPORT_STATE_STORE(access_implicit,
-				tg_pt_gp_alua_access_type, TPGS_IMPLICIT_ALUA);
-SE_DEV_ALUA_TG_PT_ATTR(alua_access_implicit, S_IRUGO | S_IWUSR);
+SE_DEV_ALUA_SUPPORT_STATE_SHOW(management_implicit,
+			       tg_pt_gp_alua_mgmt_type, ALUA_MGMT_IMPLICIT);
+SE_DEV_ALUA_SUPPORT_STATE_STORE(management_implicit,
+				tg_pt_gp_alua_mgmt_type, ALUA_MGMT_IMPLICIT);
+SE_DEV_ALUA_TG_PT_ATTR(alua_management_implicit, S_IRUGO | S_IWUSR);
 
-SE_DEV_ALUA_SUPPORT_STATE_SHOW(access_explicit,
-			       tg_pt_gp_alua_access_type, TPGS_EXPLICIT_ALUA);
-SE_DEV_ALUA_SUPPORT_STATE_STORE(access_explicit,
-				tg_pt_gp_alua_access_type, TPGS_EXPLICIT_ALUA);
-SE_DEV_ALUA_TG_PT_ATTR(alua_access_explicit, S_IRUGO | S_IWUSR);
+SE_DEV_ALUA_SUPPORT_STATE_SHOW(management_explicit,
+			       tg_pt_gp_alua_mgmt_type, ALUA_MGMT_EXPLICIT);
+SE_DEV_ALUA_SUPPORT_STATE_STORE(management_explicit,
+				tg_pt_gp_alua_mgmt_type, ALUA_MGMT_EXPLICIT);
+SE_DEV_ALUA_TG_PT_ATTR(alua_management_explicit, S_IRUGO | S_IWUSR);
 
 
 /*
@@ -2433,8 +2433,8 @@ CONFIGFS_EATTR_OPS(target_core_alua_tg_pt_gp, t10_alua_tg_pt_gp,
 static struct configfs_attribute *target_core_alua_tg_pt_gp_attrs[] = {
 	&target_core_alua_tg_pt_gp_alua_access_state.attr,
 	&target_core_alua_tg_pt_gp_alua_access_status.attr,
-	&target_core_alua_tg_pt_gp_alua_access_implicit.attr,
-	&target_core_alua_tg_pt_gp_alua_access_explicit.attr,
+	&target_core_alua_tg_pt_gp_alua_management_implicit.attr,
+	&target_core_alua_tg_pt_gp_alua_management_explicit.attr,
 	&target_core_alua_tg_pt_gp_alua_support_transitioning.attr,
 	&target_core_alua_tg_pt_gp_alua_support_offline.attr,
 	&target_core_alua_tg_pt_gp_alua_support_lba_dependent.attr,
drivers/target/target_core_spc.c +1 -1
index 021c3f4..49947f3 100644
@@ -62,7 +62,7 @@ static void spc_fill_alua_data(struct se_port *port, unsigned char *buf)
 	spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 	tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
 	if (tg_pt_gp)
-		buf[5] |= tg_pt_gp->tg_pt_gp_alua_access_type;
+		buf[5] |= tg_pt_gp->tg_pt_gp_alua_mgmt_type;
 	spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
 }
 
include/target/target_core_base.h +1 -1
index a23785f..e3e334d 100644
@@ -285,7 +285,7 @@ struct t10_alua_tg_pt_gp {
 	int	tg_pt_gp_valid_id;
 	int	tg_pt_gp_alua_supported_states;
 	int	tg_pt_gp_alua_access_status;
-	int	tg_pt_gp_alua_access_type;
+	int	tg_pt_gp_alua_mgmt_type;
 	int	tg_pt_gp_nonop_delay_msecs;
 	int	tg_pt_gp_trans_delay_msecs;
 	int	tg_pt_gp_implicit_trans_secs;
Signature · 1 line
1.7.12.4
#16 lore raw

PATCH v2 10/18 target_core: Rename alua_access_status to alua_status_modification

In reply to Hannes Reinecke

It is utterly confusing to have an attribute 'alua_access_state' and another one 'alua_access_status'. So rename the latter to 'alua_status_modification' to avoid the confusion and better reflect that actual usage.

---
 drivers/target/target_core_alua.c     | 10 +++++-----
 drivers/target/target_core_configfs.c | 14 +++++++-------
 include/target/target_core_base.h     |  2 +-
 3 files changed, 13 insertions(+), 13 deletions(-)
drivers/target/target_core_alua.c +5 -5
index 5540aae..661ee1b 100644
@@ -128,7 +128,7 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd)
 		/*
 		 * STATUS CODE
 		 */
-		buf[off++] = (tg_pt_gp->tg_pt_gp_alua_access_status & 0xff);
+		buf[off++] = (tg_pt_gp->tg_pt_gp_alua_status_modification & 0xff);
 		/*
 		 * Vendor Specific field
 		 */
@@ -764,9 +764,9 @@ static int core_alua_update_tpg_primary_metadata(
 	len = snprintf(md_buf, tg_pt_gp->tg_pt_gp_md_buf_len,
 			"tg_pt_gp_id=%hu\n"
 			"alua_access_state=0x%02x\n"
-			"alua_access_status=0x%02x\n",
+			"alua_status_modification=0x%02x\n",
 			tg_pt_gp->tg_pt_gp_id, primary_state,
-			tg_pt_gp->tg_pt_gp_alua_access_status);
+			tg_pt_gp->tg_pt_gp_alua_status_modification);
 
 	snprintf(path, ALUA_METADATA_PATH_LEN,
 		"/var/target/alua/tpgs_%s/%s", &wwn->unit_serial[0],
@@ -795,7 +795,7 @@ static int core_alua_do_transition_tg_pt(
 	old_state = atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_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) ?
+	tg_pt_gp->tg_pt_gp_alua_status_modification = (explicit) ?
 				ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG :
 				ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA;
 	/*
@@ -1653,7 +1653,7 @@ ssize_t core_alua_show_tg_pt_gp_info(struct se_port *port, char *page)
 			core_alua_dump_state(atomic_read(
 					&tg_pt_gp->tg_pt_gp_alua_access_state)),
 			core_alua_dump_status(
-				tg_pt_gp->tg_pt_gp_alua_access_status),
+				tg_pt_gp->tg_pt_gp_alua_status_modification),
 			(atomic_read(&port->sep_tg_pt_secondary_offline)) ?
 			"Offline" : "None",
 			core_alua_dump_status(port->sep_tg_pt_secondary_stat));
drivers/target/target_core_configfs.c +7 -7
index c16eb87..9ba6828 100644
@@ -2067,17 +2067,17 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state(
 SE_DEV_ALUA_TG_PT_ATTR(alua_access_state, S_IRUGO | S_IWUSR);
 
 /*
- * alua_access_status
+ * alua_status_modification
  */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_access_status(
+static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_status_modification(
 	struct t10_alua_tg_pt_gp *tg_pt_gp,
 	char *page)
 {
 	return sprintf(page, "%s\n",
-		core_alua_dump_status(tg_pt_gp->tg_pt_gp_alua_access_status));
+		core_alua_dump_status(tg_pt_gp->tg_pt_gp_alua_status_modification));
 }
 
-static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_status(
+static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_status_modification(
 	struct t10_alua_tg_pt_gp *tg_pt_gp,
 	const char *page,
 	size_t count)
@@ -2108,11 +2108,11 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_status(
 		return -EINVAL;
 	}
 
-	tg_pt_gp->tg_pt_gp_alua_access_status = new_status;
+	tg_pt_gp->tg_pt_gp_alua_status_modification = new_status;
 	return count;
 }
 
-SE_DEV_ALUA_TG_PT_ATTR(alua_access_status, S_IRUGO | S_IWUSR);
+SE_DEV_ALUA_TG_PT_ATTR(alua_status_modification, S_IRUGO | S_IWUSR);
 
 #define SE_DEV_ALUA_SUPPORT_STATE_SHOW(_name, _var, _bit)		\
 static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_##_name(	\
@@ -2432,7 +2432,7 @@ CONFIGFS_EATTR_OPS(target_core_alua_tg_pt_gp, t10_alua_tg_pt_gp,
 
 static struct configfs_attribute *target_core_alua_tg_pt_gp_attrs[] = {
 	&target_core_alua_tg_pt_gp_alua_access_state.attr,
-	&target_core_alua_tg_pt_gp_alua_access_status.attr,
+	&target_core_alua_tg_pt_gp_alua_status_modification.attr,
 	&target_core_alua_tg_pt_gp_alua_management_implicit.attr,
 	&target_core_alua_tg_pt_gp_alua_management_explicit.attr,
 	&target_core_alua_tg_pt_gp_alua_support_transitioning.attr,
include/target/target_core_base.h +1 -1
index e3e334d..6944c75 100644
@@ -284,7 +284,7 @@ struct t10_alua_tg_pt_gp {
 	u16	tg_pt_gp_id;
 	int	tg_pt_gp_valid_id;
 	int	tg_pt_gp_alua_supported_states;
-	int	tg_pt_gp_alua_access_status;
+	int	tg_pt_gp_alua_status_modification;
 	int	tg_pt_gp_alua_mgmt_type;
 	int	tg_pt_gp_nonop_delay_msecs;
 	int	tg_pt_gp_trans_delay_msecs;
Signature · 1 line
1.7.12.4
#17 lore raw

PATCH v2 11/18 target_core_alua: Validate ALUA state transition

In reply to Hannes Reinecke

As we now can modify the list of supported states we need to validate the requested ALUA state when doing a state transition.

---
 drivers/target/target_core_alua.c | 117 +++++++++++++++++++++++---------------
 1 file changed, 72 insertions(+), 45 deletions(-)
drivers/target/target_core_alua.c +72 -45
index 661ee1b..2e7110a 100644
@@ -41,7 +41,8 @@
 #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);
@@ -210,7 +211,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 +253,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 +265,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
@@ -614,36 +617,20 @@ out:
 	return 0;
 }
 
-/*
- * Check implicit and explicit ALUA state change request.
- */
-static sense_reason_t
-core_alua_check_transition(int state, int *primary)
+int core_alua_parse_state(const char *state)
 {
-	switch (state) {
-	case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED:
-	case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
-	case ALUA_ACCESS_STATE_STANDBY:
-	case ALUA_ACCESS_STATE_UNAVAILABLE:
-		/*
-		 * OPTIMIZED, NON-OPTIMIZED, STANDBY and UNAVAILABLE are
-		 * defined as primary target port asymmetric access states.
-		 */
-		*primary = 1;
-		break;
-	case ALUA_ACCESS_STATE_OFFLINE:
-		/*
-		 * OFFLINE state is defined as a secondary target port
-		 * asymmetric access state.
-		 */
-		*primary = 0;
-		break;
-	default:
-		pr_err("Unknown ALUA access state: 0x%02x\n", state);
-		return TCM_INVALID_PARAMETER_LIST;
-	}
+	if (!strncasecmp(state, "Active/Optimized", 16))
+		return ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED;
+	if (!strncasecmp(state, "Active/NonOptimized", 19))
+		return ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED;
+	if (!strncasecmp(state, "Standby", 7))
+		return ALUA_ACCESS_STATE_STANDBY;
+	if (!strncasecmp(state, "Unavailable", 11))
+		return ALUA_ACCESS_STATE_UNAVAILABLE;
+	if (!strncasecmp(state, "Offline", 7))
+		return ALUA_ACCESS_STATE_OFFLINE;
 
-	return 0;
+	return -1;
 }
 
 char *core_alua_dump_state(int state)
@@ -659,6 +646,8 @@ 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";
 	}
@@ -666,20 +655,57 @@ char *core_alua_dump_state(int state)
 	return NULL;
 }
 
-int core_alua_parse_state(const char *state)
+/*
+ * Check implicit and explicit ALUA state change request.
+ */
+static sense_reason_t
+core_alua_check_transition(int state, int valid, int *primary)
 {
-	if (!strncasecmp(state, "Active/Optimized", 16))
-		return ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED;
-	if (!strncasecmp(state, "Active/NonOptimized", 19))
-		return ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED;
-	if (!strncasecmp(state, "Standby", 7))
-		return ALUA_ACCESS_STATE_STANDBY;
-	if (!strncasecmp(state, "Unavailable", 11))
-		return ALUA_ACCESS_STATE_UNAVAILABLE;
-	if (!strncasecmp(state, "Offline", 7))
-		return ALUA_ACCESS_STATE_OFFLINE;
+	/*
+	 * 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:
+		if (!(valid & ALUA_U_SUP))
+			goto not_supported;
+		*primary = 1;
+		break;
+	case ALUA_ACCESS_STATE_OFFLINE:
+		/*
+		 * OFFLINE state is defined as a secondary target port
+		 * asymmetric access state.
+		 */
+		if (!(valid & ALUA_O_SUP))
+			goto not_supported;
+		*primary = 0;
+		break;
+	default:
+		pr_err("Unknown ALUA access state: 0x%02x\n", state);
+		return TCM_INVALID_PARAMETER_LIST;
+	}
 
-	return -1;
+	return 0;
+
+not_supported:
+	pr_err("ALUA access state %s not supported",
+	       core_alua_dump_state(state));
+	return TCM_INVALID_PARAMETER_LIST;
 }
 
 char *core_alua_dump_status(int status)
@@ -900,9 +926,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);
Signature · 1 line
1.7.12.4
#18 lore raw

PATCH v2 12/18 target_core_alua: Allocate ALUA metadata on demand

In reply to Hannes Reinecke

We should only allocate ALUA metadata if we're actually going to write them.

---
 drivers/target/target_core_alua.c | 70 +++++++++++++++++----------------------
 drivers/target/target_core_alua.h |  3 ++
 include/target/target_core_base.h |  3 --
 3 files changed, 34 insertions(+), 42 deletions(-)
drivers/target/target_core_alua.c +31 -39
index 2e7110a..3fa535c 100644
@@ -778,16 +778,22 @@ static int core_alua_write_tpg_metadata(
  */
 static int core_alua_update_tpg_primary_metadata(
 	struct t10_alua_tg_pt_gp *tg_pt_gp,
-	int primary_state,
-	unsigned char *md_buf)
+	int primary_state)
 {
+	unsigned char *md_buf;
 	struct t10_wwn *wwn = &tg_pt_gp->tg_pt_gp_dev->t10_wwn;
 	char path[ALUA_METADATA_PATH_LEN];
-	int len;
+	int len, rc;
+
+	md_buf = kzalloc(ALUA_MD_BUF_LEN, GFP_KERNEL);
+	if (!md_buf) {
+		pr_err("Unable to allocate buf for ALUA metadata\n");
+		return -ENOMEM;
+	}
 
 	memset(path, 0, ALUA_METADATA_PATH_LEN);
 
-	len = snprintf(md_buf, tg_pt_gp->tg_pt_gp_md_buf_len,
+	len = snprintf(md_buf, ALUA_MD_BUF_LEN,
 			"tg_pt_gp_id=%hu\n"
 			"alua_access_state=0x%02x\n"
 			"alua_status_modification=0x%02x\n",
@@ -798,14 +804,15 @@ static int core_alua_update_tpg_primary_metadata(
 		"/var/target/alua/tpgs_%s/%s", &wwn->unit_serial[0],
 		config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item));
 
-	return core_alua_write_tpg_metadata(path, md_buf, len);
+	rc = core_alua_write_tpg_metadata(path, md_buf, len);
+	kfree(md_buf);
+	return rc;
 }
 
 static int core_alua_do_transition_tg_pt(
 	struct t10_alua_tg_pt_gp *tg_pt_gp,
 	struct se_port *l_port,
 	struct se_node_acl *nacl,
-	unsigned char *md_buf,
 	int new_state,
 	int explicit)
 {
@@ -893,8 +900,7 @@ static int core_alua_do_transition_tg_pt(
 	 */
 	if (tg_pt_gp->tg_pt_gp_write_metadata) {
 		mutex_lock(&tg_pt_gp->tg_pt_gp_md_mutex);
-		core_alua_update_tpg_primary_metadata(tg_pt_gp,
-					new_state, md_buf);
+		core_alua_update_tpg_primary_metadata(tg_pt_gp, new_state);
 		mutex_unlock(&tg_pt_gp->tg_pt_gp_md_mutex);
 	}
 	/*
@@ -925,19 +931,12 @@ int core_alua_do_port_transition(
 	struct t10_alua_lu_gp *lu_gp;
 	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, valid_states;
 
 	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);
-	if (!md_buf) {
-		pr_err("Unable to allocate buf for ALUA metadata\n");
-		return -ENOMEM;
-	}
-
 	local_lu_gp_mem = l_dev->dev_alua_lu_gp_mem;
 	spin_lock(&local_lu_gp_mem->lu_gp_mem_lock);
 	lu_gp = local_lu_gp_mem->lu_gp;
@@ -955,10 +954,9 @@ int core_alua_do_port_transition(
 		 * success.
 		 */
 		core_alua_do_transition_tg_pt(l_tg_pt_gp, l_port, l_nacl,
-					md_buf, new_state, explicit);
+					new_state, explicit);
 		atomic_dec(&lu_gp->lu_gp_ref_cnt);
 		smp_mb__after_atomic_dec();
-		kfree(md_buf);
 		return 0;
 	}
 	/*
@@ -1008,7 +1006,7 @@ int core_alua_do_port_transition(
 			 * success.
 			 */
 			core_alua_do_transition_tg_pt(tg_pt_gp, port,
-					nacl, md_buf, new_state, explicit);
+					nacl, new_state, explicit);
 
 			spin_lock(&dev->t10_alua.tg_pt_gps_lock);
 			atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
@@ -1030,7 +1028,6 @@ int core_alua_do_port_transition(
 
 	atomic_dec(&lu_gp->lu_gp_ref_cnt);
 	smp_mb__after_atomic_dec();
-	kfree(md_buf);
 	return 0;
 }
 
@@ -1039,13 +1036,18 @@ int core_alua_do_port_transition(
  */
 static int core_alua_update_tpg_secondary_metadata(
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem,
-	struct se_port *port,
-	unsigned char *md_buf,
-	u32 md_buf_len)
+	struct se_port *port)
 {
+	unsigned char *md_buf;
 	struct se_portal_group *se_tpg = port->sep_tpg;
 	char path[ALUA_METADATA_PATH_LEN], wwn[ALUA_SECONDARY_METADATA_WWN_LEN];
-	int len;
+	int len, rc;
+
+	md_buf = kzalloc(ALUA_MD_BUF_LEN, GFP_KERNEL);
+	if (!md_buf) {
+		pr_err("Unable to allocate buf for ALUA metadata\n");
+		return -ENOMEM;
+	}
 
 	memset(path, 0, ALUA_METADATA_PATH_LEN);
 	memset(wwn, 0, ALUA_SECONDARY_METADATA_WWN_LEN);
@@ -1057,7 +1059,7 @@ static int core_alua_update_tpg_secondary_metadata(
 		snprintf(wwn+len, ALUA_SECONDARY_METADATA_WWN_LEN-len, "+%hu",
 				se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg));
 
-	len = snprintf(md_buf, md_buf_len, "alua_tg_pt_offline=%d\n"
+	len = snprintf(md_buf, ALUA_MD_BUF_LEN, "alua_tg_pt_offline=%d\n"
 			"alua_tg_pt_status=0x%02x\n",
 			atomic_read(&port->sep_tg_pt_secondary_offline),
 			port->sep_tg_pt_secondary_stat);
@@ -1066,7 +1068,10 @@ static int core_alua_update_tpg_secondary_metadata(
 			se_tpg->se_tpg_tfo->get_fabric_name(), wwn,
 			port->sep_lun->unpacked_lun);
 
-	return core_alua_write_tpg_metadata(path, md_buf, len);
+	rc = core_alua_write_tpg_metadata(path, md_buf, len);
+	kfree(md_buf);
+
+	return rc;
 }
 
 static int core_alua_set_tg_pt_secondary_state(
@@ -1076,8 +1081,6 @@ static int core_alua_set_tg_pt_secondary_state(
 	int offline)
 {
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
-	unsigned char *md_buf;
-	u32 md_buf_len;
 	int trans_delay_msecs;
 
 	spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
@@ -1098,7 +1101,6 @@ static int core_alua_set_tg_pt_secondary_state(
 	else
 		atomic_set(&port->sep_tg_pt_secondary_offline, 0);
 
-	md_buf_len = tg_pt_gp->tg_pt_gp_md_buf_len;
 	port->sep_tg_pt_secondary_stat = (explicit) ?
 			ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG :
 			ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA;
@@ -1120,18 +1122,9 @@ static int core_alua_set_tg_pt_secondary_state(
 	 * secondary state and status
 	 */
 	if (port->sep_tg_pt_secondary_write_md) {
-		md_buf = kzalloc(md_buf_len, GFP_KERNEL);
-		if (!md_buf) {
-			pr_err("Unable to allocate md_buf for"
-				" secondary ALUA access metadata\n");
-			return -ENOMEM;
-		}
 		mutex_lock(&port->sep_tg_pt_md_mutex);
-		core_alua_update_tpg_secondary_metadata(tg_pt_gp_mem, port,
-				md_buf, md_buf_len);
+		core_alua_update_tpg_secondary_metadata(tg_pt_gp_mem, port);
 		mutex_unlock(&port->sep_tg_pt_md_mutex);
-
-		kfree(md_buf);
 	}
 
 	return 0;
@@ -1390,7 +1383,6 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev,
 	spin_lock_init(&tg_pt_gp->tg_pt_gp_lock);
 	atomic_set(&tg_pt_gp->tg_pt_gp_ref_cnt, 0);
 	tg_pt_gp->tg_pt_gp_dev = dev;
-	tg_pt_gp->tg_pt_gp_md_buf_len = ALUA_MD_BUF_LEN;
 	atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
 		ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED);
 	/*
drivers/target/target_core_alua.h +3 -0
index 299dc33..f2c1ef3 100644
@@ -78,6 +78,9 @@
  */
 #define ALUA_SECONDARY_METADATA_WWN_LEN			256
 
+/* Used by core_alua_update_tpg_(primary,secondary)_metadata */
+#define ALUA_MD_BUF_LEN					1024
+
 extern struct kmem_cache *t10_alua_lu_gp_cache;
 extern struct kmem_cache *t10_alua_lu_gp_mem_cache;
 extern struct kmem_cache *t10_alua_tg_pt_gp_cache;
include/target/target_core_base.h +0 -3
index 6944c75..faf7de0 100644
@@ -291,9 +291,6 @@ struct t10_alua_tg_pt_gp {
 	int	tg_pt_gp_implicit_trans_secs;
 	int	tg_pt_gp_pref;
 	int	tg_pt_gp_write_metadata;
-	/* Used by struct t10_alua_tg_pt_gp->tg_pt_gp_md_buf_len */
-#define ALUA_MD_BUF_LEN				1024
-	u32	tg_pt_gp_md_buf_len;
 	u32	tg_pt_gp_members;
 	atomic_t tg_pt_gp_alua_access_state;
 	atomic_t tg_pt_gp_ref_cnt;
Signature · 1 line
1.7.12.4
#19 lore raw

PATCH v2 13/18 target_core_alua: store old and pending ALUA state

In reply to Hannes Reinecke

During state transition we should be storing both the original and the pending state.

---
 drivers/target/target_core_alua.c | 15 ++++++++++-----
 include/target/target_core_base.h |  6 ++++--
 2 files changed, 14 insertions(+), 7 deletions(-)
drivers/target/target_core_alua.c +10 -5
index 3fa535c..5de2ea1 100644
@@ -820,12 +820,15 @@ static int core_alua_do_transition_tg_pt(
 	struct se_lun_acl *lacl;
 	struct se_port *port;
 	struct t10_alua_tg_pt_gp_member *mem;
-	int old_state = 0;
+
 	/*
 	 * Save the old primary ALUA access state, and set the current state
 	 * to ALUA_ACCESS_STATE_TRANSITION.
 	 */
-	old_state = atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state);
+	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_status_modification = (explicit) ?
@@ -906,13 +909,15 @@ static int core_alua_do_transition_tg_pt(
 	/*
 	 * Set the current primary ALUA access state to the requested new state
 	 */
-	atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, new_state);
+	atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
+		   tg_pt_gp->tg_pt_gp_alua_pending_state);
 
 	pr_debug("Successful %s ALUA transition TG PT Group: %s ID: %hu"
 		" from primary access state %s to %s\n", (explicit) ? "explicit" :
 		"implicit", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item),
-		tg_pt_gp->tg_pt_gp_id, core_alua_dump_state(old_state),
-		core_alua_dump_state(new_state));
+		tg_pt_gp->tg_pt_gp_id,
+		core_alua_dump_state(tg_pt_gp->tg_pt_gp_alua_previous_state),
+		core_alua_dump_state(tg_pt_gp->tg_pt_gp_alua_pending_state));
 
 	return 0;
 }
include/target/target_core_base.h +4 -2
index faf7de0..b8b7ec8 100644
@@ -283,8 +283,10 @@ struct t10_alua_lu_gp_member {
 struct t10_alua_tg_pt_gp {
 	u16	tg_pt_gp_id;
 	int	tg_pt_gp_valid_id;
-	int	tg_pt_gp_alua_supported_states;
-	int	tg_pt_gp_alua_status_modification;
+	u8	tg_pt_gp_alua_pending_state;
+	u8	tg_pt_gp_alua_previous_state;
+	u8	tg_pt_gp_alua_supported_states;
+	u8	tg_pt_gp_alua_status_modification;
 	int	tg_pt_gp_alua_mgmt_type;
 	int	tg_pt_gp_nonop_delay_msecs;
 	int	tg_pt_gp_trans_delay_msecs;
Signature · 1 line
1.7.12.4
#20 lore raw

PATCH v2 14/18 target_core_alua: Use workqueue for ALUA transitioning

In reply to Hannes Reinecke

Use a workqueue for processing ALUA state transitions; this allows us to process implicit delay properly.

---
 drivers/target/target_core_alua.c | 174 +++++++++++++++++++++++++++-----------
 include/target/target_core_base.h |   4 +
 2 files changed, 128 insertions(+), 50 deletions(-)
drivers/target/target_core_alua.c +124 -50
index 5de2ea1..19179cf 100644
@@ -777,8 +777,7 @@ static int core_alua_write_tpg_metadata(
  * Called with tg_pt_gp->tg_pt_gp_md_mutex held
  */
 static int core_alua_update_tpg_primary_metadata(
-	struct t10_alua_tg_pt_gp *tg_pt_gp,
-	int primary_state)
+	struct t10_alua_tg_pt_gp *tg_pt_gp)
 {
 	unsigned char *md_buf;
 	struct t10_wwn *wwn = &tg_pt_gp->tg_pt_gp_dev->t10_wwn;
@@ -797,7 +796,8 @@ static int core_alua_update_tpg_primary_metadata(
 			"tg_pt_gp_id=%hu\n"
 			"alua_access_state=0x%02x\n"
 			"alua_status_modification=0x%02x\n",
-			tg_pt_gp->tg_pt_gp_id, primary_state,
+			tg_pt_gp->tg_pt_gp_id,
+			tg_pt_gp->tg_pt_gp_alua_pending_state,
 			tg_pt_gp->tg_pt_gp_alua_status_modification);
 
 	snprintf(path, ALUA_METADATA_PATH_LEN,
@@ -809,36 +809,17 @@ static int core_alua_update_tpg_primary_metadata(
 	return rc;
 }
 
-static int core_alua_do_transition_tg_pt(
-	struct t10_alua_tg_pt_gp *tg_pt_gp,
-	struct se_port *l_port,
-	struct se_node_acl *nacl,
-	int new_state,
-	int explicit)
+static void core_alua_do_transition_tg_pt_work(struct work_struct *work)
 {
+	struct t10_alua_tg_pt_gp *tg_pt_gp = container_of(work,
+		struct t10_alua_tg_pt_gp, tg_pt_gp_transition_work.work);
+	struct se_device *dev = tg_pt_gp->tg_pt_gp_dev;
 	struct se_dev_entry *se_deve;
 	struct se_lun_acl *lacl;
 	struct se_port *port;
 	struct t10_alua_tg_pt_gp_member *mem;
-
-	/*
-	 * 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_status_modification = (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);
+	bool explicit = (tg_pt_gp->tg_pt_gp_alua_status_modification ==
+			 ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG);
 
 	spin_lock(&tg_pt_gp->tg_pt_gp_lock);
 	list_for_each_entry(mem, &tg_pt_gp->tg_pt_gp_mem_list,
@@ -873,9 +854,12 @@ static int core_alua_do_transition_tg_pt(
 			if (!lacl)
 				continue;
 
-			if (explicit &&
-			   (nacl != NULL) && (nacl == lacl->se_lun_nacl) &&
-			   (l_port != NULL) && (l_port == port))
+			if ((tg_pt_gp->tg_pt_gp_alua_status_modification ==
+			     ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG) &&
+			   (tg_pt_gp->tg_pt_gp_alua_nacl != NULL) &&
+			    (tg_pt_gp->tg_pt_gp_alua_nacl == lacl->se_lun_nacl) &&
+			   (tg_pt_gp->tg_pt_gp_alua_port != NULL) &&
+			    (tg_pt_gp->tg_pt_gp_alua_port == port))
 				continue;
 
 			core_scsi3_ua_allocate(lacl->se_lun_nacl,
@@ -903,7 +887,7 @@ static int core_alua_do_transition_tg_pt(
 	 */
 	if (tg_pt_gp->tg_pt_gp_write_metadata) {
 		mutex_lock(&tg_pt_gp->tg_pt_gp_md_mutex);
-		core_alua_update_tpg_primary_metadata(tg_pt_gp, new_state);
+		core_alua_update_tpg_primary_metadata(tg_pt_gp);
 		mutex_unlock(&tg_pt_gp->tg_pt_gp_md_mutex);
 	}
 	/*
@@ -918,6 +902,87 @@ static int core_alua_do_transition_tg_pt(
 		tg_pt_gp->tg_pt_gp_id,
 		core_alua_dump_state(tg_pt_gp->tg_pt_gp_alua_previous_state),
 		core_alua_dump_state(tg_pt_gp->tg_pt_gp_alua_pending_state));
+	spin_lock(&dev->t10_alua.tg_pt_gps_lock);
+	atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
+	smp_mb__after_atomic_dec();
+	spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
+
+	if (tg_pt_gp->tg_pt_gp_transition_complete)
+		complete(tg_pt_gp->tg_pt_gp_transition_complete);
+}
+
+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_status_modification = (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;
+	}
 
 	return 0;
 }
@@ -931,12 +996,10 @@ int core_alua_do_port_transition(
 	int explicit)
 {
 	struct se_device *dev;
-	struct se_port *port;
-	struct se_node_acl *nacl;
 	struct t10_alua_lu_gp *lu_gp;
 	struct t10_alua_lu_gp_member *lu_gp_mem, *local_lu_gp_mem;
 	struct t10_alua_tg_pt_gp *tg_pt_gp;
-	int primary, valid_states;
+	int primary, valid_states, rc = 0;
 
 	valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states;
 	if (core_alua_check_transition(new_state, valid_states, &primary) != 0)
@@ -958,11 +1021,13 @@ int core_alua_do_port_transition(
 		 * core_alua_do_transition_tg_pt() will always return
 		 * success.
 		 */
-		core_alua_do_transition_tg_pt(l_tg_pt_gp, l_port, l_nacl,
-					new_state, explicit);
+		l_tg_pt_gp->tg_pt_gp_alua_port = l_port;
+		l_tg_pt_gp->tg_pt_gp_alua_nacl = l_nacl;
+		rc = core_alua_do_transition_tg_pt(l_tg_pt_gp,
+						   new_state, explicit);
 		atomic_dec(&lu_gp->lu_gp_ref_cnt);
 		smp_mb__after_atomic_dec();
-		return 0;
+		return rc;
 	}
 	/*
 	 * For all other LU groups aside from 'default_lu_gp', walk all of
@@ -997,11 +1062,11 @@ int core_alua_do_port_transition(
 				continue;
 
 			if (l_tg_pt_gp == tg_pt_gp) {
-				port = l_port;
-				nacl = l_nacl;
+				tg_pt_gp->tg_pt_gp_alua_port = l_port;
+				tg_pt_gp->tg_pt_gp_alua_nacl = l_nacl;
 			} else {
-				port = NULL;
-				nacl = NULL;
+				tg_pt_gp->tg_pt_gp_alua_port = NULL;
+				tg_pt_gp->tg_pt_gp_alua_nacl = NULL;
 			}
 			atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt);
 			smp_mb__after_atomic_inc();
@@ -1010,12 +1075,14 @@ int core_alua_do_port_transition(
 			 * core_alua_do_transition_tg_pt() will always return
 			 * success.
 			 */
-			core_alua_do_transition_tg_pt(tg_pt_gp, port,
-					nacl, new_state, explicit);
+			rc = core_alua_do_transition_tg_pt(tg_pt_gp,
+					new_state, explicit);
 
 			spin_lock(&dev->t10_alua.tg_pt_gps_lock);
 			atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
 			smp_mb__after_atomic_dec();
+			if (rc)
+				break;
 		}
 		spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 
@@ -1025,15 +1092,18 @@ int core_alua_do_port_transition(
 	}
 	spin_unlock(&lu_gp->lu_gp_lock);
 
-	pr_debug("Successfully processed LU Group: %s all ALUA TG PT"
-		" Group IDs: %hu %s transition to primary state: %s\n",
-		config_item_name(&lu_gp->lu_gp_group.cg_item),
-		l_tg_pt_gp->tg_pt_gp_id, (explicit) ? "explicit" : "implicit",
-		core_alua_dump_state(new_state));
+	if (!rc) {
+		pr_debug("Successfully processed LU Group: %s all ALUA TG PT"
+			 " Group IDs: %hu %s transition to primary state: %s\n",
+			 config_item_name(&lu_gp->lu_gp_group.cg_item),
+			 l_tg_pt_gp->tg_pt_gp_id,
+			 (explicit) ? "explicit" : "implicit",
+			 core_alua_dump_state(new_state));
+	}
 
 	atomic_dec(&lu_gp->lu_gp_ref_cnt);
 	smp_mb__after_atomic_dec();
-	return 0;
+	return rc;
 }
 
 /*
@@ -1387,6 +1457,8 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev,
 	mutex_init(&tg_pt_gp->tg_pt_gp_md_mutex);
 	spin_lock_init(&tg_pt_gp->tg_pt_gp_lock);
 	atomic_set(&tg_pt_gp->tg_pt_gp_ref_cnt, 0);
+	INIT_DELAYED_WORK(&tg_pt_gp->tg_pt_gp_transition_work,
+			  core_alua_do_transition_tg_pt_work);
 	tg_pt_gp->tg_pt_gp_dev = dev;
 	atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
 		ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED);
@@ -1515,6 +1587,8 @@ void core_alua_free_tg_pt_gp(
 	dev->t10_alua.alua_tg_pt_gps_counter--;
 	spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 
+	flush_delayed_work(&tg_pt_gp->tg_pt_gp_transition_work);
+
 	/*
 	 * Allow a struct t10_alua_tg_pt_gp_member * referenced by
 	 * core_alua_get_tg_pt_gp_by_name() in
include/target/target_core_base.h +4 -0
index b8b7ec8..b95c1f1 100644
@@ -302,6 +302,10 @@ struct t10_alua_tg_pt_gp {
 	struct config_group tg_pt_gp_group;
 	struct list_head tg_pt_gp_list;
 	struct list_head tg_pt_gp_mem_list;
+	struct se_port *tg_pt_gp_alua_port;
+	struct se_node_acl *tg_pt_gp_alua_nacl;
+	struct delayed_work tg_pt_gp_transition_work;
+	struct completion *tg_pt_gp_transition_complete;
 };
 
 struct t10_alua_tg_pt_gp_member {
Signature · 1 line
1.7.12.4
#21 lore raw

PATCH v2 15/18 target_core: simplify scsi_name_len calculation

In reply to Hannes Reinecke

scsi_name_len in spc_emulate_evpd_83 is calculated twice, with the results of the first calculation discarded. So remove it. And check for the maximum allowed length, too.

---
 drivers/target/target_core_spc.c | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)
drivers/target/target_core_spc.c +3 -10
index 49947f3..0fde086 100644
@@ -365,16 +365,6 @@ check_lu_gp:
 		 * section 7.5.1 Table 362
 		 */
 check_scsi_name:
-		scsi_name_len = strlen(tpg->se_tpg_tfo->tpg_get_wwn(tpg));
-		/* UTF-8 ",t,0x<16-bit TPGT>" + NULL Terminator */
-		scsi_name_len += 10;
-		/* Check for 4-byte padding */
-		padding = ((-scsi_name_len) & 3);
-		if (padding != 0)
-			scsi_name_len += padding;
-		/* Header size + Designation descriptor */
-		scsi_name_len += 4;
-
 		buf[off] =
 			(tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
 		buf[off++] |= 0x3; /* CODE SET == UTF-8 */
@@ -402,8 +392,11 @@ check_scsi_name:
 		 * shall be no larger than 256 and shall be a multiple
 		 * of four.
 		 */
+		padding = ((-scsi_name_len) & 3);
 		if (padding)
 			scsi_name_len += padding;
+		if (scsi_name_len > 256)
+			scsi_name_len = 256;
 
 		buf[off-1] = scsi_name_len;
 		off += scsi_name_len;
Signature · 1 line
1.7.12.4
#22 lore raw

PATCH v2 16/18 target_core_spc: Include target device descriptor in VPD page 83

In reply to Hannes Reinecke

We should be including a descriptor referring to the target device to allow identification of different TCM instances.

---
 drivers/target/target_core_spc.c | 43 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)
drivers/target/target_core_spc.c +42 -1
index 0fde086..44e8d69 100644
@@ -267,7 +267,7 @@ check_t10_vend_desc:
 	port = lun->lun_sep;
 	if (port) {
 		struct t10_alua_lu_gp *lu_gp;
-		u32 padding, scsi_name_len;
+		u32 padding, scsi_name_len, scsi_target_len;
 		u16 lu_gp_id = 0;
 		u16 tg_pt_gp_id = 0;
 		u16 tpgt;
@@ -402,6 +402,47 @@ check_scsi_name:
 		off += scsi_name_len;
 		/* Header size + Designation descriptor */
 		len += (scsi_name_len + 4);
+
+		/*
+		 * Target device designator
+		 */
+		buf[off] =
+			(tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
+		buf[off++] |= 0x3; /* CODE SET == UTF-8 */
+		buf[off] = 0x80; /* Set PIV=1 */
+		/* Set ASSOCIATION == target device: 10b */
+		buf[off] |= 0x20;
+		/* DESIGNATOR TYPE == SCSI name string */
+		buf[off++] |= 0x8;
+		off += 2; /* Skip over Reserved and length */
+		/*
+		 * SCSI name string identifer containing, $FABRIC_MOD
+		 * dependent information.  For LIO-Target and iSCSI
+		 * Target Port, this means "<iSCSI name>" in
+		 * UTF-8 encoding.
+		 */
+		scsi_target_len = sprintf(&buf[off], "%s",
+					  tpg->se_tpg_tfo->tpg_get_wwn(tpg));
+		scsi_target_len += 1 /* Include  NULL terminator */;
+		/*
+		 * The null-terminated, null-padded (see 4.4.2) SCSI
+		 * NAME STRING field contains a UTF-8 format string.
+		 * The number of bytes in the SCSI NAME STRING field
+		 * (i.e., the value in the DESIGNATOR LENGTH field)
+		 * shall be no larger than 256 and shall be a multiple
+		 * of four.
+		 */
+		padding = ((-scsi_target_len) & 3);
+		if (padding)
+			scsi_target_len += padding;
+		if (scsi_name_len > 256)
+			scsi_name_len = 256;
+
+		buf[off-1] = scsi_target_len;
+		off += scsi_target_len;
+
+		/* Header size + Designation descriptor */
+		len += (scsi_target_len + 4);
 	}
 	buf[2] = ((len >> 8) & 0xff);
 	buf[3] = (len & 0xff); /* Page Length for VPD 0x83 */
Signature · 1 line
1.7.12.4
#23 lore raw

PATCH v2 17/18 target_core_alua: Referrals infrastructure

In reply to Hannes Reinecke

Add infrastructure for referrals.

---
 drivers/target/target_core_alua.c     | 155 ++++++++++++++++++++++++++++++++++
 drivers/target/target_core_alua.h     |   4 +-
 drivers/target/target_core_configfs.c |   9 +-
 drivers/target/target_core_device.c   |   2 +
 drivers/target/target_core_sbc.c      |   5 +-
 drivers/target/target_core_spc.c      |  20 +++++
 include/scsi/scsi.h                   |   1 +
 include/target/target_core_base.h     |  18 ++++
 8 files changed, 211 insertions(+), 3 deletions(-)
drivers/target/target_core_alua.c +155 -0
index 19179cf..5b11908 100644
@@ -56,6 +56,75 @@ static LIST_HEAD(lu_gps_list);
 struct t10_alua_lu_gp *default_lu_gp;
 
 /*
+ * REPORT REFERRALS
+ *
+ * See sbc3r35 section 5.23
+ */
+sense_reason_t
+target_emulate_report_referrals(struct se_cmd *cmd)
+{
+	struct se_device *dev = cmd->se_dev;
+	struct t10_alua_lba_map *map;
+	struct t10_alua_lba_map_member *map_mem;
+	unsigned char *buf;
+	u32 rd_len = 0, off;
+
+	if (cmd->data_length < 4) {
+		pr_warn("REPORT REFERRALS allocation length %u too"
+			" small\n", cmd->data_length);
+		return TCM_INVALID_CDB_FIELD;
+	}
+
+	buf = transport_kmap_data_sg(cmd);
+	if (!buf)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+	off = 4;
+	spin_lock(&dev->t10_alua.lba_map_lock);
+	if (list_empty(&dev->t10_alua.lba_map_list)) {
+		spin_unlock(&dev->t10_alua.lba_map_lock);
+		transport_kunmap_data_sg(cmd);
+
+		return TCM_UNSUPPORTED_SCSI_OPCODE;
+	}
+
+	list_for_each_entry(map, &dev->t10_alua.lba_map_list,
+			    lba_map_list) {
+		int desc_num = off + 3;
+		int pg_num;
+
+		off += 4;
+		put_unaligned_be64(map->lba_map_first_lba, &buf[off]);
+		off += 8;
+		put_unaligned_be64(map->lba_map_last_lba, &buf[off]);
+		off += 8;
+		rd_len += 20;
+		pg_num = 0;
+		list_for_each_entry(map_mem, &map->lba_map_mem_list,
+				    lba_map_mem_list) {
+			buf[off++] = map_mem->lba_map_mem_alua_state & 0x0f;
+			off++;
+			buf[off++] = (map_mem->lba_map_mem_alua_pg_id >> 8) & 0xff;
+			buf[off++] = (map_mem->lba_map_mem_alua_pg_id & 0xff);
+			rd_len += 4;
+			pg_num++;
+		}
+		buf[desc_num] = pg_num;
+	}
+	spin_unlock(&dev->t10_alua.lba_map_lock);
+
+	/*
+	 * Set the RETURN DATA LENGTH set in the header of the DataIN Payload
+	 */
+	put_unaligned_be16(rd_len, &buf[2]);
+
+	transport_kunmap_data_sg(cmd);
+
+	target_complete_cmd(cmd, GOOD);
+	return 0;
+}
+
+/*
  * REPORT_TARGET_PORT_GROUPS
  *
  * See spc4r17 section 6.27
@@ -389,6 +458,80 @@ static inline int core_alua_state_nonoptimized(
 	return 0;
 }
 
+static inline int core_alua_state_lba_dependent(
+	struct se_cmd *cmd,
+	struct t10_alua_tg_pt_gp *tg_pt_gp,
+	u8 *alua_ascq)
+{
+	struct se_device *dev = cmd->se_dev;
+	u32 segment_size, segment_mult, sectors;
+	u64 lba;
+
+	/* Only need to check for cdb actually containing LBAs */
+	if (!cmd->se_cmd_flags & SCF_SCSI_DATA_CDB)
+		return 0;
+
+	spin_lock(&dev->t10_alua.lba_map_lock);
+	segment_size = dev->t10_alua.lba_map_segment_size;
+	segment_mult = dev->t10_alua.lba_map_segment_multiplier;
+	sectors = cmd->data_length / dev->dev_attrib.block_size;
+
+	lba = cmd->t_task_lba;
+	while (lba < cmd->t_task_lba + sectors) {
+		struct t10_alua_lba_map *cur_map = NULL, *map;
+		struct t10_alua_lba_map_member *map_mem;
+
+		list_for_each_entry(map, &dev->t10_alua.lba_map_list,
+				    lba_map_list) {
+			u64 start_lba, last_lba;
+			u64 first_lba = map->lba_map_first_lba;
+
+			if (segment_mult) {
+				start_lba = lba % (segment_size * segment_mult);
+				last_lba = first_lba + segment_size - 1;
+				if (start_lba >= first_lba &&
+				    start_lba <= last_lba) {
+					lba += segment_size;
+					cur_map = map;
+					break;
+				}
+			} else {
+				last_lba = map->lba_map_last_lba;
+				if (lba >= first_lba && lba <= last_lba) {
+					lba = last_lba + 1;
+					cur_map = map;
+					break;
+				}
+			}
+		}
+		if (!cur_map) {
+			spin_unlock(&dev->t10_alua.lba_map_lock);
+			*alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE;
+			return 1;
+		}
+		list_for_each_entry(map_mem, &cur_map->lba_map_mem_list,
+				    lba_map_mem_list) {
+			if (map_mem->lba_map_mem_alua_pg_id !=
+			    tg_pt_gp->tg_pt_gp_id)
+				continue;
+			switch(map_mem->lba_map_mem_alua_state) {
+			case ALUA_ACCESS_STATE_STANDBY:
+				spin_unlock(&dev->t10_alua.lba_map_lock);
+				*alua_ascq = ASCQ_04H_ALUA_TG_PT_STANDBY;
+				return 1;
+			case ALUA_ACCESS_STATE_UNAVAILABLE:
+				spin_unlock(&dev->t10_alua.lba_map_lock);
+				*alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE;
+				return 1;
+			default:
+				break;
+			}
+		}
+	}
+	spin_unlock(&dev->t10_alua.lba_map_lock);
+	return 0;
+}
+
 static inline int core_alua_state_standby(
 	struct se_cmd *cmd,
 	unsigned char *cdb,
@@ -586,6 +729,9 @@ target_alua_state_check(struct se_cmd *cmd)
 	case ALUA_ACCESS_STATE_TRANSITION:
 		ret = core_alua_state_transition(cmd, cdb, &alua_ascq);
 		break;
+	case ALUA_ACCESS_STATE_LBA_DEPENDENT:
+		ret = core_alua_state_lba_dependent(cmd, tg_pt_gp, &alua_ascq);
+		break;
 	/*
 	 * OFFLINE is a secondary ALUA target port group access state, that is
 	 * handled above with struct se_port->sep_tg_pt_secondary_offline=1
@@ -623,6 +769,8 @@ int core_alua_parse_state(const char *state)
 		return ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED;
 	if (!strncasecmp(state, "Active/NonOptimized", 19))
 		return ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED;
+	if (!strncasecmp(state, "LBA Dependent", 19))
+		return ALUA_ACCESS_STATE_LBA_DEPENDENT;
 	if (!strncasecmp(state, "Standby", 7))
 		return ALUA_ACCESS_STATE_STANDBY;
 	if (!strncasecmp(state, "Unavailable", 11))
@@ -640,6 +788,8 @@ char *core_alua_dump_state(int state)
 		return "Active/Optimized";
 	case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
 		return "Active/NonOptimized";
+	case ALUA_ACCESS_STATE_LBA_DEPENDENT:
+		return "LBA Dependent";
 	case ALUA_ACCESS_STATE_STANDBY:
 		return "Standby";
 	case ALUA_ACCESS_STATE_UNAVAILABLE:
@@ -686,6 +836,11 @@ core_alua_check_transition(int state, int valid, int *primary)
 			goto not_supported;
 		*primary = 1;
 		break;
+	case ALUA_ACCESS_STATE_LBA_DEPENDENT:
+		if (!(valid & ALUA_LBD_SUP))
+			goto not_supported;
+		*primary = 1;
+		break;
 	case ALUA_ACCESS_STATE_OFFLINE:
 		/*
 		 * OFFLINE state is defined as a secondary target port
drivers/target/target_core_alua.h +3 -1
index f2c1ef3..e4ba452 100644
@@ -13,12 +13,13 @@
 /*
  * ASYMMETRIC ACCESS STATE field
  *
- * from spc4r17 section 6.27 Table 245
+ * from spc4r36j section 6.37 Table 307
  */
 #define ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED	0x0
 #define ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED	0x1
 #define ALUA_ACCESS_STATE_STANDBY		0x2
 #define ALUA_ACCESS_STATE_UNAVAILABLE		0x3
+#define ALUA_ACCESS_STATE_LBA_DEPENDENT		0x4
 #define ALUA_ACCESS_STATE_OFFLINE		0xe
 #define ALUA_ACCESS_STATE_TRANSITION		0xf
 
@@ -88,6 +89,7 @@ extern struct kmem_cache *t10_alua_tg_pt_gp_mem_cache;
 
 extern sense_reason_t target_emulate_report_target_port_groups(struct se_cmd *);
 extern sense_reason_t target_emulate_set_target_port_groups(struct se_cmd *);
+extern sense_reason_t target_emulate_report_referrals(struct se_cmd *);
 extern int core_alua_check_nonop_delay(struct se_cmd *);
 extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *,
 				struct se_device *, struct se_port *,
drivers/target/target_core_configfs.c +8 -1
index 9ba6828..50f058c 100644
@@ -2059,6 +2059,13 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state(
 		}
 		new_state = (int)tmp;
 	}
+	if (tg_pt_gp->tg_pt_gp_alua_mgmt_type & ALUA_MGMT_EXPLICIT &&
+	    new_state == ALUA_ACCESS_STATE_LBA_DEPENDENT) {
+		/* LBA DEPENDENT is only allowed with implicit ALUA */
+		pr_err("Unable to process implicit configfs ALUA transition"
+		       " while explicit ALUA management is enabled\n");
+		return -EINVAL;
+	}
 	ret = core_alua_do_port_transition(tg_pt_gp, dev,
 					NULL, NULL, new_state, 0);
 	return (!ret) ? count : -EINVAL;
@@ -2188,7 +2195,7 @@ SE_DEV_ALUA_SUPPORT_STATE_SHOW(support_lba_dependent,
 			       tg_pt_gp_alua_supported_states, ALUA_LBD_SUP);
 SE_DEV_ALUA_SUPPORT_STATE_STORE(support_lba_dependent,
 				tg_pt_gp_alua_supported_states, ALUA_LBD_SUP);
-SE_DEV_ALUA_TG_PT_ATTR(alua_support_lba_dependent, S_IRUGO | S_IWUSR);
+SE_DEV_ALUA_TG_PT_ATTR(alua_support_lba_dependent, S_IRUGO);
 
 SE_DEV_ALUA_SUPPORT_STATE_SHOW(support_unavailable,
 			       tg_pt_gp_alua_supported_states, ALUA_U_SUP);
drivers/target/target_core_device.c +2 -0
index 207b340..3c08f99 100644
@@ -1439,6 +1439,8 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
 	spin_lock_init(&dev->t10_pr.aptpl_reg_lock);
 	INIT_LIST_HEAD(&dev->t10_alua.tg_pt_gps_list);
 	spin_lock_init(&dev->t10_alua.tg_pt_gps_lock);
+	INIT_LIST_HEAD(&dev->t10_alua.lba_map_list);
+	spin_lock_init(&dev->t10_alua.lba_map_lock);
 
 	dev->t10_wwn.t10_dev = dev;
 	dev->t10_alua.t10_dev = dev;
drivers/target/target_core_sbc.c +4 -1
index 61a30f0..daaddc7 100644
@@ -33,7 +33,7 @@
 
 #include "target_core_internal.h"
 #include "target_core_ua.h"
-
+#include "target_core_alua.h"
 
 static sense_reason_t
 sbc_emulate_readcapacity(struct se_cmd *cmd)
@@ -702,6 +702,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
 		case SAI_READ_CAPACITY_16:
 			cmd->execute_cmd = sbc_emulate_readcapacity_16;
 			break;
+		case SAI_REPORT_REFERRALS:
+			cmd->execute_cmd = target_emulate_report_referrals;
+			break;
 		default:
 			pr_err("Unsupported SA: 0x%02x\n",
 				cmd->t_task_cdb[1] & 0x1f);
drivers/target/target_core_spc.c +20 -0
index 44e8d69..5d86813 100644
@@ -476,6 +476,11 @@ spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
 	/* If WriteCache emulation is enabled, set V_SUP */
 	if (spc_check_dev_wce(dev))
 		buf[6] = 0x01;
+	/* If an LBA map is present set R_SUP */
+	spin_lock(&cmd->se_dev->t10_alua.lba_map_lock);
+	if (!list_empty(&dev->t10_alua.lba_map_list))
+		buf[8] = 0x10;
+	spin_unlock(&cmd->se_dev->t10_alua.lba_map_lock);
 	return 0;
 }
 
@@ -634,6 +639,20 @@ spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
 	return 0;
 }
 
+/* Referrals VPD page */
+static sense_reason_t
+spc_emulate_evpd_b3(struct se_cmd *cmd, unsigned char *buf)
+{
+	struct se_device *dev = cmd->se_dev;
+
+	buf[0] = dev->transport->get_device_type(dev);
+	buf[3] = 0x0c;
+	put_unaligned_be32(dev->t10_alua.lba_map_segment_size, &buf[8]);
+	put_unaligned_be32(dev->t10_alua.lba_map_segment_size, &buf[12]);
+
+	return 0;
+}
+
 static sense_reason_t
 spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf);
 
@@ -648,6 +667,7 @@ static struct {
 	{ .page = 0xb0, .emulate = spc_emulate_evpd_b0 },
 	{ .page = 0xb1, .emulate = spc_emulate_evpd_b1 },
 	{ .page = 0xb2, .emulate = spc_emulate_evpd_b2 },
+	{ .page = 0xb3, .emulate = spc_emulate_evpd_b3 },
 };
 
 /* supported vital product data pages */
include/scsi/scsi.h +1 -0
index 66d42ed..0a4edfe 100644
@@ -155,6 +155,7 @@ enum scsi_timeouts {
 /* values for service action in */
 #define	SAI_READ_CAPACITY_16  0x10
 #define SAI_GET_LBA_STATUS    0x12
+#define SAI_REPORT_REFERRALS  0x13
 /* values for VARIABLE_LENGTH_CMD service action codes
  * see spc4r17 Section D.3.5, table D.7 and D.8 */
 #define VLC_SA_RECEIVE_CREDENTIAL 0x1800
include/target/target_core_base.h +18 -0
index b95c1f1..ab66b87 100644
@@ -247,10 +247,28 @@ typedef enum {
 
 struct se_cmd;
 
+struct t10_alua_lba_map_member {
+	struct list_head lba_map_mem_list;
+	int lba_map_mem_alua_state;
+	int lba_map_mem_alua_pg_id;
+};
+
+struct t10_alua_lba_map {
+	u64 lba_map_first_lba;
+	u64 lba_map_last_lba;
+	struct list_head lba_map_list;
+	struct list_head lba_map_mem_list;
+};
+
 struct t10_alua {
 	/* ALUA Target Port Group ID */
 	u16	alua_tg_pt_gps_counter;
 	u32	alua_tg_pt_gps_count;
+	/* Referrals support */
+	spinlock_t lba_map_lock;
+	u32     lba_map_segment_size;
+	u32     lba_map_segment_multiplier;
+	struct list_head lba_map_list;
 	spinlock_t tg_pt_gps_lock;
 	struct se_device *t10_dev;
 	/* Used for default ALUA Target Port Group */
Signature · 1 line
1.7.12.4
#24 lore raw

PATCH v2 18/18 target_core_alua: Referrals configfs integration

In reply to Hannes Reinecke

Referrals need an LBA map, which needs to be kept consistent across all target port groups. So instead of tying the map to the target port groups I've implemented a single attribute containing the entire map.

---
 drivers/target/target_core_alua.c      | 101 +++++++++++++++++++
 drivers/target/target_core_alua.h      |   8 ++
 drivers/target/target_core_configfs.c  | 171 +++++++++++++++++++++++++++++++++
 drivers/target/target_core_device.c    |   1 +
 drivers/target/target_core_transport.c |  28 +++++-
 5 files changed, 308 insertions(+), 1 deletion(-)
drivers/target/target_core_alua.c +101 -0
index 5b11908..b1c33e8 100644
@@ -1360,6 +1360,107 @@ static int core_alua_set_tg_pt_secondary_state(
 	return 0;
 }
 
+struct t10_alua_lba_map *
+core_alua_allocate_lba_map(struct list_head *list,
+			   u64 first_lba, u64 last_lba)
+{
+	struct t10_alua_lba_map *lba_map;
+
+	lba_map = kmem_cache_zalloc(t10_alua_lba_map_cache, GFP_KERNEL);
+	if (!lba_map) {
+		pr_err("Unable to allocate struct t10_alua_lba_map\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	INIT_LIST_HEAD(&lba_map->lba_map_mem_list);
+	lba_map->lba_map_first_lba = first_lba;
+	lba_map->lba_map_last_lba = last_lba;
+
+	list_add_tail(&lba_map->lba_map_list, list);
+	return lba_map;
+}
+
+int
+core_alua_allocate_lba_map_mem(struct t10_alua_lba_map *lba_map,
+			       int pg_id, int state)
+{
+	struct t10_alua_lba_map_member *lba_map_mem;
+
+	list_for_each_entry(lba_map_mem, &lba_map->lba_map_mem_list,
+			    lba_map_mem_list) {
+		if (lba_map_mem->lba_map_mem_alua_pg_id == pg_id) {
+			pr_err("Duplicate pg_id %d in lba_map\n", pg_id);
+			return -EINVAL;
+		}
+	}
+
+	lba_map_mem = kmem_cache_zalloc(t10_alua_lba_map_mem_cache, GFP_KERNEL);
+	if (!lba_map_mem) {
+		pr_err("Unable to allocate struct t10_alua_lba_map_mem\n");
+		return -ENOMEM;
+	}
+	lba_map_mem->lba_map_mem_alua_state = state;
+	lba_map_mem->lba_map_mem_alua_pg_id = pg_id;
+
+	list_add_tail(&lba_map_mem->lba_map_mem_list,
+		      &lba_map->lba_map_mem_list);
+	return 0;
+}
+
+void
+core_alua_free_lba_map(struct list_head *lba_list)
+{
+	struct t10_alua_lba_map *lba_map, *lba_map_tmp;
+	struct t10_alua_lba_map_member *lba_map_mem, *lba_map_mem_tmp;
+
+	list_for_each_entry_safe(lba_map, lba_map_tmp, lba_list,
+				 lba_map_list) {
+		list_for_each_entry_safe(lba_map_mem, lba_map_mem_tmp,
+					 &lba_map->lba_map_mem_list,
+					 lba_map_mem_list) {
+			list_del(&lba_map_mem->lba_map_mem_list);
+			kmem_cache_free(t10_alua_lba_map_mem_cache,
+					lba_map_mem);
+		}
+		list_del(&lba_map->lba_map_list);
+		kmem_cache_free(t10_alua_lba_map_cache, lba_map);
+	}
+}
+
+void
+core_alua_set_lba_map(struct se_device *dev, struct list_head *lba_map_list,
+		      int segment_size, int segment_mult)
+{
+	struct list_head old_lba_map_list;
+	struct t10_alua_tg_pt_gp *tg_pt_gp;
+	int activate = 0, supported;
+
+	INIT_LIST_HEAD(&old_lba_map_list);
+	spin_lock(&dev->t10_alua.lba_map_lock);
+	dev->t10_alua.lba_map_segment_size = segment_size;
+	dev->t10_alua.lba_map_segment_multiplier = segment_mult;
+	list_splice_init(&dev->t10_alua.lba_map_list, &old_lba_map_list);
+	if (lba_map_list) {
+		list_splice_init(lba_map_list, &dev->t10_alua.lba_map_list);
+		activate = 1;
+	}
+	spin_unlock(&dev->t10_alua.lba_map_lock);
+	spin_lock(&dev->t10_alua.tg_pt_gps_lock);
+	list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list,
+			    tg_pt_gp_list) {
+
+		if (!tg_pt_gp->tg_pt_gp_valid_id)
+			continue;
+		supported = tg_pt_gp->tg_pt_gp_alua_supported_states;
+		if (activate)
+			supported |= ALUA_LBD_SUP;
+		else
+			supported &= ~ALUA_LBD_SUP;
+		tg_pt_gp->tg_pt_gp_alua_supported_states = supported;
+	}
+	spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
+	core_alua_free_lba_map(&old_lba_map_list);
+}
+
 struct t10_alua_lu_gp *
 core_alua_allocate_lu_gp(const char *name, int def_group)
 {
drivers/target/target_core_alua.h +8 -0
index e4ba452..c83935c 100644
@@ -86,6 +86,8 @@ extern struct kmem_cache *t10_alua_lu_gp_cache;
 extern struct kmem_cache *t10_alua_lu_gp_mem_cache;
 extern struct kmem_cache *t10_alua_tg_pt_gp_cache;
 extern struct kmem_cache *t10_alua_tg_pt_gp_mem_cache;
+extern struct kmem_cache *t10_alua_lba_map_cache;
+extern struct kmem_cache *t10_alua_lba_map_mem_cache;
 
 extern sense_reason_t target_emulate_report_target_port_groups(struct se_cmd *);
 extern sense_reason_t target_emulate_set_target_port_groups(struct se_cmd *);
@@ -97,6 +99,12 @@ extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *,
 extern char *core_alua_dump_state(int);
 extern int core_alua_parse_state(const char *);
 extern char *core_alua_dump_status(int);
+extern struct t10_alua_lba_map *core_alua_allocate_lba_map(
+				struct list_head *, u64, u64);
+extern int core_alua_allocate_lba_map_mem(struct t10_alua_lba_map *, int, int);
+extern void core_alua_free_lba_map(struct list_head *);
+extern void core_alua_set_lba_map(struct se_device *, struct list_head *,
+				int, int);
 extern struct t10_alua_lu_gp *core_alua_allocate_lu_gp(const char *, int);
 extern int core_alua_set_lu_gp_id(struct t10_alua_lu_gp *, u16);
 extern void core_alua_free_lu_gp(struct t10_alua_lu_gp *);
drivers/target/target_core_configfs.c +171 -0

183 lines not on this page · raw message

drivers/target/target_core_device.c +1 -0
index 3c08f99..376a4d3 100644
@@ -1585,6 +1585,7 @@ void target_free_device(struct se_device *dev)
 	}
 
 	core_alua_free_lu_gp_mem(dev);
+	core_alua_set_lba_map(dev, NULL, 0, 0);
 	core_scsi3_free_all_registrations(dev);
 	se_release_vpd_for_dev(dev);
 
drivers/target/target_core_transport.c +27 -1
index 269a798..ea4dc1b 100644
@@ -62,6 +62,8 @@ struct kmem_cache *t10_alua_lu_gp_cache;
 struct kmem_cache *t10_alua_lu_gp_mem_cache;
 struct kmem_cache *t10_alua_tg_pt_gp_cache;
 struct kmem_cache *t10_alua_tg_pt_gp_mem_cache;
+struct kmem_cache *t10_alua_lba_map_cache;
+struct kmem_cache *t10_alua_lba_map_mem_cache;
 
 static void transport_complete_task_attr(struct se_cmd *cmd);
 static void transport_handle_queue_full(struct se_cmd *cmd,
@@ -128,14 +130,36 @@ int init_se_kmem_caches(void)
 				"mem_t failed\n");
 		goto out_free_tg_pt_gp_cache;
 	}
+	t10_alua_lba_map_cache = kmem_cache_create(
+			"t10_alua_lba_map_cache",
+			sizeof(struct t10_alua_lba_map),
+			__alignof__(struct t10_alua_lba_map), 0, NULL);
+	if (!t10_alua_lba_map_cache) {
+		pr_err("kmem_cache_create() for t10_alua_lba_map_"
+				"cache failed\n");
+		goto out_free_tg_pt_gp_mem_cache;
+	}
+	t10_alua_lba_map_mem_cache = kmem_cache_create(
+			"t10_alua_lba_map_mem_cache",
+			sizeof(struct t10_alua_lba_map_member),
+			__alignof__(struct t10_alua_lba_map_member), 0, NULL);
+	if (!t10_alua_lba_map_mem_cache) {
+		pr_err("kmem_cache_create() for t10_alua_lba_map_mem_"
+				"cache failed\n");
+		goto out_free_lba_map_cache;
+	}
 
 	target_completion_wq = alloc_workqueue("target_completion",
 					       WQ_MEM_RECLAIM, 0);
 	if (!target_completion_wq)
-		goto out_free_tg_pt_gp_mem_cache;
+		goto out_free_lba_map_mem_cache;
 
 	return 0;
 
+out_free_lba_map_mem_cache:
+	kmem_cache_destroy(t10_alua_lba_map_mem_cache);
+out_free_lba_map_cache:
+	kmem_cache_destroy(t10_alua_lba_map_cache);
 out_free_tg_pt_gp_mem_cache:
 	kmem_cache_destroy(t10_alua_tg_pt_gp_mem_cache);
 out_free_tg_pt_gp_cache:
@@ -164,6 +188,8 @@ void release_se_kmem_caches(void)
 	kmem_cache_destroy(t10_alua_lu_gp_mem_cache);
 	kmem_cache_destroy(t10_alua_tg_pt_gp_cache);
 	kmem_cache_destroy(t10_alua_tg_pt_gp_mem_cache);
+	kmem_cache_destroy(t10_alua_lba_map_cache);
+	kmem_cache_destroy(t10_alua_lba_map_mem_cache);
 }
 
 /* This code ensures unique mib indexes are handed out. */
Signature · 1 line
1.7.12.4
#25 lore raw
In reply to Hannes Reinecke

Hey Hannes!

Quoted 24 lines · Hannes Reinecke

Hi Nic,

here's the second version of my ALUA update & Referrals support patches. As per request I've split up the supported states into individual attributes, and while there I've also renamed the rather confusing 'alua_access_type' and 'alua_access_status' into 'alua_management_type' and 'alua_status_modification', respectively.

The other features are:

- Make supported states configurable:
We should make the list of supported ALUA states configurable, as some setups would possibly like to support a small subset of ALUA states only.
- Asynchronous transitioning: I've switched 'transitioning' handling to use a workqueue, that should allow us to simulate asynchronous transitioning modes. IE TCM should now be capable of handling requests while in transitioning, and properly terminate these with the correct sense code.
- Include target device descriptor in VPD page 83
For the ALUA device handler we'd need to identify the target device where a given target port belongs to. So include the respective values in the VPD page.

Quoted 2 lines

And, of course, referrals support.

Ok, even though it is late, I've applied this series to for-next.

So the one main concern here is that the user visible changes to existing ALUA configfs attributes end up breaking the lio-utils code related to ALUA that depend upon them, which will need to be resolved separately.

However, this breakage is pretty minor and having more sensible + consistent attribute naming is worth the inconvenience.

--nab

#26 lore raw
Quoted 32 lines · Nicholas A. Bellinger

Hey Hannes!

Quoted 24 lines · Hannes Reinecke

Hi Nic,

here's the second version of my ALUA update & Referrals support patches. As per request I've split up the supported states into individual attributes, and while there I've also renamed the rather confusing 'alua_access_type' and 'alua_access_status' into 'alua_management_type' and 'alua_status_modification', respectively.

The other features are:

- Make supported states configurable:
We should make the list of supported ALUA states configurable, as some setups would possibly like to support a small subset of ALUA states only.
- Asynchronous transitioning: I've switched 'transitioning' handling to use a workqueue, that should allow us to simulate asynchronous transitioning modes. IE TCM should now be capable of handling requests while in transitioning, and properly terminate these with the correct sense code.
- Include target device descriptor in VPD page 83
For the ALUA device handler we'd need to identify the target device where a given target port belongs to. So include the respective values in the VPD page.

Quoted 2 lines

And, of course, referrals support.

Ok, even though it is late, I've applied this series to for-next.

Quoted 8 lines

So the one main concern here is that the user visible changes to existing ALUA configfs attributes end up breaking the lio-utils code related to ALUA that depend upon them, which will need to be resolved separately.

However, this breakage is pretty minor and having more sensible + consistent attribute naming is worth the inconvenience.

OK, I'm having second thoughts about the user-visible changes to existing configfs attributes..

I'm fine with these types of changes, but need some more time to sort out how it's going to effect existing userspace dependencies. The one that immediately made do a double take is changing 'alua_access_state' to change input/output, but keep the same attribute name which makes backwards compatibility alot more tricky.

So all that said, let's defer to v3.14 for this particular series, and sort out the user visable changes first, and make adjustments as necessary from there.

WDYT..?

--nab

#27 lore raw
Quoted 42 lines · Nicholas A. Bellinger
Quoted 32 lines · Nicholas A. Bellinger

Hey Hannes!

Quoted 24 lines · Hannes Reinecke

Hi Nic,

here's the second version of my ALUA update & Referrals support patches. As per request I've split up the supported states into individual attributes, and while there I've also renamed the rather confusing 'alua_access_type' and 'alua_access_status' into 'alua_management_type' and 'alua_status_modification', respectively.

The other features are:

- Make supported states configurable:
We should make the list of supported ALUA states configurable, as some setups would possibly like to support a small subset of ALUA states only.
- Asynchronous transitioning: I've switched 'transitioning' handling to use a workqueue, that should allow us to simulate asynchronous transitioning modes. IE TCM should now be capable of handling requests while in transitioning, and properly terminate these with the correct sense code.
- Include target device descriptor in VPD page 83
For the ALUA device handler we'd need to identify the target device where a given target port belongs to. So include the respective values in the VPD page.

Quoted 2 lines

And, of course, referrals support.

Ok, even though it is late, I've applied this series to for-next.

Quoted 8 lines

So the one main concern here is that the user visible changes to existing ALUA configfs attributes end up breaking the lio-utils code related to ALUA that depend upon them, which will need to be resolved separately.

However, this breakage is pretty minor and having more sensible + consistent attribute naming is worth the inconvenience.

Quoted 9 lines

OK, I'm having second thoughts about the user-visible changes to existing configfs attributes..

I'm fine with these types of changes, but need some more time to sort out how it's going to effect existing userspace dependencies. The one that immediately made do a double take is changing 'alua_access_state' to change input/output, but keep the same attribute name which makes backwards compatibility alot more tricky.

It's just a matter of parsing, innit?

Quoted 6 lines

So all that said, let's defer to v3.14 for this particular series, and sort out the user visable changes first, and make adjustments as necessary from there.

WDYT..?

Sigh.
Another patchset getting nowhere.

Okay, here's the thing:
The patchset can be split into three individual parts:
The ALUA update proper, which affects only the internal flow of control (patches 1-6 and 11-16), then there's the ALUA configfs modifications (patches 7-10) and the Referrals support (17 and 18). If you have second thoughts you should be able to pull patches 7-10; the rest will work as designed even without them.

But then, there's not much difference on having all the patches in for 3.13, and sort out the userspace then, or wait for the next round and adjust the userspace during that time.

Anyway, I don't mind either way. You're the maintainer, you get to decide. As least I got feedback about the patchset, which is more than one can hope for nowadays :-(

Give me a shout what you prefer, and I'll adapt the patchset accordingly.

Cheers,

Hannes

Signature · 4 lines
Dr. Hannes Reinecke		      zSeries & Storage
[email protected]			      +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
#28 lore raw
Quoted 13 lines · Hannes Reinecke
Quoted 12 lines · Nicholas A. Bellinger
Quoted 11 lines · Nicholas A. Bellinger

Hey Hannes!

Quoted 8 lines · Hannes Reinecke

Hi Nic,

here's the second version of my ALUA update & Referrals support patches. As per request I've split up the supported states into individual attributes, and while there I've also renamed the rather confusing 'alua_access_type' and 'alua_access_status' into 'alua_management_type' and 'alua_status_modification', respectively.

<SNIP>

Quoted 12 lines
Quoted 10 lines

OK, I'm having second thoughts about the user-visible changes to existing configfs attributes..

I'm fine with these types of changes, but need some more time to sort out how it's going to effect existing userspace dependencies. The one that immediately made do a double take is changing 'alua_access_state' to change input/output, but keep the same attribute name which makes backwards compatibility alot more tricky.

It's just a matter of parsing, innit?

Quoted 9 lines
Quoted 6 lines

So all that said, let's defer to v3.14 for this particular series, and sort out the user visable changes first, and make adjustments as necessary from there.

WDYT..?

Sigh.
Another patchset getting nowhere.

Awww, I like to think target-pending is still a whole lot more merge friendly than linux-scsi. ;)

Quoted 7 lines

Okay, here's the thing:
The patchset can be split into three individual parts:
The ALUA update proper, which affects only the internal flow of control (patches 1-6 and 11-16), then there's the ALUA configfs modifications (patches 7-10) and the Referrals support (17 and 18). If you have second thoughts you should be able to pull patches 7-10; the rest will work as designed even without them.

Ok, I'm completely fine with patches 1-6, which only add new attributes and don't change input/output or rename existing attributes.

It's 7-10 that introduce the changes that are of concern..

Quoted 4 lines

But then, there's not much difference on having all the patches in for 3.13, and sort out the userspace then, or wait for the next round and adjust the userspace during that time.

As much as I'd like to merge this now, the changes to existing attributes is what needs to be thought out some more, to avoid overt backwards compatibility ugliness.

Quoted 3 lines

Anyway, I don't mind either way. You're the maintainer, you get to decide. As least I got feedback about the patchset, which is more than one can hope for nowadays :-(

Lets merge 1-6 now for v3.13, and I'll merge the rest for v3.14 into for-next as soon as -rc1 is released, and we can duke it out on the specific details starting next week.

--nab

#29 lore raw
Quoted 15 lines · Nicholas A. Bellinger
Quoted 13 lines · Hannes Reinecke
Quoted 12 lines · Nicholas A. Bellinger
Quoted 11 lines · Nicholas A. Bellinger

Hey Hannes!

Quoted 8 lines · Hannes Reinecke

Hi Nic,

here's the second version of my ALUA update & Referrals support patches. As per request I've split up the supported states into individual attributes, and while there I've also renamed the rather confusing 'alua_access_type' and 'alua_access_status' into 'alua_management_type' and 'alua_status_modification', respectively.

<SNIP>

Quoted 22 lines
Quoted 7 lines

Okay, here's the thing:
The patchset can be split into three individual parts:
The ALUA update proper, which affects only the internal flow of control (patches 1-6 and 11-16), then there's the ALUA configfs modifications (patches 7-10) and the Referrals support (17 and 18). If you have second thoughts you should be able to pull patches 7-10; the rest will work as designed even without them.

Ok, I'm completely fine with patches 1-6, which only add new attributes and don't change input/output or rename existing attributes.

It's 7-10 that introduce the changes that are of concern..

Quoted 4 lines

But then, there's not much difference on having all the patches in for 3.13, and sort out the userspace then, or wait for the next round and adjust the userspace during that time.

As much as I'd like to merge this now, the changes to existing attributes is what needs to be thought out some more, to avoid overt backwards compatibility ugliness.

Quoted 8 lines
Quoted 3 lines

Anyway, I don't mind either way. You're the maintainer, you get to decide. As least I got feedback about the patchset, which is more than one can hope for nowadays :-(

Lets merge 1-6 now for v3.13, and I'll merge the rest for v3.14 into for-next as soon as -rc1 is released, and we can duke it out on the specific details starting next week.

Ok, a bit longer than next week for getting back to this series, but now I've a better idea where the user visable changes should end up..

What I'd really like to see for -v3 is:

Patch 7: Keep alua_access_state attribute store/show formatting (as is). Patch 8: Keep alua_access_type attribute store/show formatting (as is)
within a single attribute + drop support_* prefix to alua_supported_states attributes merged in v3.13
Patch 9: Drop alua_access_type attribute rename

So AFAICT none of these changes are strictly required to support Referrals. Granted, some of the early formatting decisions for these ALUA attributes did not make a ton of sense, but regardless I very much do not want name + formatting changes for existing attributes without a really good reason.

I do like the usability aspects of the proposed name + formatting changes, but these types of user facing things really should be implemented at the rtslib + targetcli level, and not as changes to existing configfs attributes.

That said, care to respin the series minus the above bits..? ;)

Thank you,

--nab

#30 lore raw
Quoted 67 lines · Nicholas A. Bellinger
Quoted 15 lines · Nicholas A. Bellinger
Quoted 13 lines · Hannes Reinecke
Quoted 12 lines · Nicholas A. Bellinger
Quoted 11 lines · Nicholas A. Bellinger

Hey Hannes!

Quoted 8 lines · Hannes Reinecke

Hi Nic,

here's the second version of my ALUA update & Referrals support patches. As per request I've split up the supported states into individual attributes, and while there I've also renamed the rather confusing 'alua_access_type' and 'alua_access_status' into 'alua_management_type' and 'alua_status_modification', respectively.

<SNIP>

Quoted 22 lines
Quoted 7 lines

Okay, here's the thing:
The patchset can be split into three individual parts:
The ALUA update proper, which affects only the internal flow of control (patches 1-6 and 11-16), then there's the ALUA configfs modifications (patches 7-10) and the Referrals support (17 and 18). If you have second thoughts you should be able to pull patches 7-10; the rest will work as designed even without them.

Ok, I'm completely fine with patches 1-6, which only add new attributes and don't change input/output or rename existing attributes.

It's 7-10 that introduce the changes that are of concern..

Quoted 4 lines

But then, there's not much difference on having all the patches in for 3.13, and sort out the userspace then, or wait for the next round and adjust the userspace during that time.

As much as I'd like to merge this now, the changes to existing attributes is what needs to be thought out some more, to avoid overt backwards compatibility ugliness.

Quoted 8 lines
Quoted 3 lines

Anyway, I don't mind either way. You're the maintainer, you get to decide. As least I got feedback about the patchset, which is more than one can hope for nowadays :-(

Lets merge 1-6 now for v3.13, and I'll merge the rest for v3.14 into for-next as soon as -rc1 is released, and we can duke it out on the specific details starting next week.

Ok, a bit longer than next week for getting back to this series, but now I've a better idea where the user visable changes should end up..

What I'd really like to see for -v3 is:

Patch 7: Keep alua_access_state attribute store/show formatting (as is). Patch 8: Keep alua_access_type attribute store/show formatting (as is)
within a single attribute + drop support_* prefix to alua_supported_states attributes merged in v3.13
Patch 9: Drop alua_access_type attribute rename

So AFAICT none of these changes are strictly required to support Referrals. Granted, some of the early formatting decisions for these ALUA attributes did not make a ton of sense, but regardless I very much do not want name + formatting changes for existing attributes without a really good reason.

Quoted 5 lines

I do like the usability aspects of the proposed name + formatting changes, but these types of user facing things really should be implemented at the rtslib + targetcli level, and not as changes to existing configfs attributes.

So the current interface is cast in stone forever? Seriously?

How does one go about modifying configfs?
There _is_ a version number in /sys/kernel/config, which is supposed to give some hints here.

And it's far easier implementing a fallback in rtslib + targetcli; having two attributes in the kernel for exposing the old and the new interface is not what I would call elegant.

But then I'm not the maintainer :-)

And as I've now separated those two issues we're having more time discussing this :-)

Quoted 2 lines

That said, care to respin the series minus the above bits..? ;)

Ok, done.

Cheers,

Hannes

Signature · 4 lines
Dr. Hannes Reinecke		      zSeries & Storage
[email protected]			      +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)