[PATCH] [Target_Core_Mod/ALUA]: Make EVPD 0x83 identifers return GOOD status during overflow

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Greetings all,

This patch makes transport_generic_emulate_inquiry() properly handle the case
where a received allocation length is smaller than the total outgoing EVPD 0x83
DataIN payload containing the full set of emulated identifiers.  This is what
scsi_dh_alua does; use an allocation length of 36 and then retry with a larger
allocation length based on what is returned in the EVPD payload during the initial
overflow case.

Instead of failing during the overflow case as before, this patch will calculate
the total size required to transmit the complete set of emulated EVPD 0x83
identifiers, and encode this value into the response payload with GOOD SAM status.
At this point the Initiator Port is expected to notice that the encoded EVPD length
is greater than the allocation length of the original CDB, and retry again with new
allocation length in order to retreive the complete set of EVPD 0x83 identifiers.

This patch is made against lio-core-2.6.git/master
and tested on v2.6.29-rc2 x86 32-bit HVM.  The lio-core-2.6.git tree can be
found at:

http://git.kernel.org/?p=linux/kernel/git/nab/lio-core-2.6.git;a=summary

Signed-off-by: Nicholas A. Bellinger <nab@xxxxxxxxxxxxxxx>
---
 drivers/lio-core/target_core_transport.c |   66 +++++++++++++-----------------
 1 files changed, 28 insertions(+), 38 deletions(-)

diff --git a/drivers/lio-core/target_core_transport.c b/drivers/lio-core/target_core_transport.c
index ae51b5f..3167486 100644
--- a/drivers/lio-core/target_core_transport.c
+++ b/drivers/lio-core/target_core_transport.c
@@ -4032,12 +4032,13 @@ extern int transport_generic_emulate_inquiry (
 	se_device_t *dev = SE_DEV(cmd);
 	se_lun_t *lun = SE_LUN(cmd);
 	se_port_t *port = NULL;
+	se_portal_group_t *tpg = NULL;
 	unsigned char *buf = (unsigned char *) T_TASK(cmd)->t_task_buf;
 	unsigned char *cdb = T_TASK(cmd)->t_task_cdb;
 	unsigned char *iqn_sn;
 	u32 vend_len, prod_len, iqn_sn_len, se_location_len;
-	u32 unit_serial_len;
-	u32 len = 0, off = 0;
+	u32 unit_serial_len, off = 0;
+	u16 len = 0;
 	
 	buf[0] = type;
 	
@@ -4067,7 +4068,7 @@ extern int transport_generic_emulate_inquiry (
 		snprintf((unsigned char *)&buf[32], 5, "%s", version);
 		len = 32;
 
-		goto check;
+		return(0);
 	}
 
 	switch (cdb[2]) {
@@ -4087,7 +4088,7 @@ extern int transport_generic_emulate_inquiry (
 
 			if (((len + 4) + unit_serial_len) > cmd->data_length) {
 				len += unit_serial_len; // Make check: below fail
-				goto check;
+				goto set_len;
 			}
 			len += sprintf((unsigned char *)&buf[4], "%s",
 				&DEV_T10_WWN(dev)->unit_serial[0]);
@@ -4101,7 +4102,7 @@ extern int transport_generic_emulate_inquiry (
 			if (((len + 4) + (iqn_sn_len + se_location_len)) >
 					cmd->data_length) {
 				len += (iqn_sn_len + se_location_len);
-				goto check;
+				goto set_len;
 			}
 			len += sprintf((unsigned char *)&buf[4], "%s:%s",
 				iqn_sn, se_location);
@@ -4118,15 +4119,9 @@ extern int transport_generic_emulate_inquiry (
 		/*
 		 * T10 Vendor Identifier Page, see spc4r17 section 7.7.3.4
 		 */
-		buf[4] = 0x2; /* ASCII */
-		buf[5] = 0x1; /* T10 Vendor ID */
-		buf[6] = 0x0;
-
-		vend_len = sprintf((unsigned char *)&buf[8], "%-8s", "LIO-ORG");		
-		len += vend_len;
-
+		len += 8; // For Vendor field
 		prod_len = 4; // For EVPD Header
-		prod_len += vend_len; // For LIO-ORG
+		prod_len += 8; // For Vendor field
 		prod_len += strlen(prod);
 		prod_len++; // For :
 
@@ -4138,7 +4133,7 @@ extern int transport_generic_emulate_inquiry (
 					cmd->data_length) {
 				// Make check: fail below
 				len += (prod_len + unit_serial_len); 
-				goto check;
+				goto check_rtpi;
 			}
 			len += sprintf((unsigned char *)&buf[16], "%s:%s", prod,
 					&DEV_T10_WWN(dev)->unit_serial[0]);
@@ -4153,11 +4148,16 @@ extern int transport_generic_emulate_inquiry (
 					cmd->data_length) {
 				// Make check: fail below
 				len += (prod_len + iqn_sn_len + se_location_len);
-				goto check; 
+				goto check_rtpi;
 			}
 			len += sprintf((unsigned char *)&buf[16], "%s:%s:%s",
 					prod, iqn_sn, se_location);
 		}
+		buf[4] = 0x2; /* ASCII */
+		buf[5] = 0x1; /* T10 Vendor ID */
+		buf[6] = 0x0;
+		memcpy((unsigned char *)&buf[8], "LIO-ORG", 8);
+
 		len++; // Extra Byte for NULL Terminator
 		buf[7] = len; // Identifier Length
 		len += 4; // Header size for Designation descriptor 
@@ -4166,20 +4166,22 @@ extern int transport_generic_emulate_inquiry (
 		 * se_port_t is only set for INQUIRY EVPD=1 through $FABRIC_MOD
 		 */
 		if ((port = lun->lun_sep)) {	
-			se_portal_group_t *tpg = port->sep_tpg;
 			u32 padding, scsi_name_len;
 			u16 lun_gp = 0;	// Set to zero for implict ALUA
 			u16 tg_pg_i = 0; // Set to zero for implict ALUA
 			u16 tpgt;
+
+			tpg = port->sep_tpg;
 			/*
 			 * Relative target port identifer, see spc4r17 section 7.7.3.7 
 			 *
 			 * Get the PROTOCOL IDENTIFIER as defined by spc4r17
 			 * section 7.5.1 Table 362
 			 */
+check_rtpi:
 			if (((len + 4) + 8) > cmd->data_length) {
 				len += 8; // Make check: below fail
-				goto check;
+				goto check_tpgi;
 			}
 			buf[off] = (TPG_TFO(tpg)->get_fabric_proto_ident() << 4); 
 			buf[off++] |= 0x1; // CODE SET == Binary 
@@ -4198,9 +4200,10 @@ extern int transport_generic_emulate_inquiry (
 			 * Get the PROTOCOL IDENTIFIER as defined by spc4r17
 			 * section 7.5.1 Table 362 
 			 */
+check_tpgi:
 			if (((len + 4) + 8) > cmd->data_length) {
 				len += 8; // Make check: below fail
-				goto check;
+				goto check_lu_gp;
 			}
 			buf[off] = (TPG_TFO(tpg)->get_fabric_proto_ident() << 4);
 			buf[off++] |= 0x1; // CODE SET == Binary
@@ -4216,9 +4219,10 @@ extern int transport_generic_emulate_inquiry (
 			/*
 			 * Logical Unit Group identifier, see spc4r17 section 7.7.3.8
 			 */	
+check_lu_gp:
 			if (((len + 4) + 8) > cmd->data_length) {
 				len += 8; // Make check: below fail
-				goto check;
+				goto check_scsi_name;
 			}
 			buf[off++] |= 0x1; // CODE SET == Binary
 			buf[off++] |= 0x6; // DESIGNATOR TYPE == Logical Unit Group identifier
@@ -4234,6 +4238,7 @@ extern int transport_generic_emulate_inquiry (
 			 * Get the PROTOCOL IDENTIFIER as defined by spc4r17
 			 * section 7.5.1 Table 362	
 			 */
+check_scsi_name:
 			scsi_name_len = strlen(TPG_TFO(tpg)->tpg_get_wwn(tpg));
 			scsi_name_len += 10; // UTF-8 ",t,0x<16-bit TPGT>" + NULL Terminator
 			scsi_name_len += 4; // Header size + Designation descriptor
@@ -4242,7 +4247,7 @@ extern int transport_generic_emulate_inquiry (
 
 			if ((len + scsi_name_len) > cmd->data_length) {
 				len += scsi_name_len; // Make check: below fail
-				goto check;
+				goto set_len;
 			}
 			buf[off] = (TPG_TFO(tpg)->get_fabric_proto_ident() << 4);
 			buf[off++] |= 0x3; // CODE SET == UTF-8
@@ -4273,30 +4278,15 @@ extern int transport_generic_emulate_inquiry (
 			off += scsi_name_len;
 			len += (scsi_name_len + 4); // Header size + Designation descriptor 
 		}
-
-		buf[3] = len; /* Page Length for EVPD 0x83 */
+set_len:
+		buf[2] = ((len >> 8) & 0xff);
+		buf[3] = (len & 0xff); /* Page Length for EVPD 0x83 */
 		break;
 	default:
 		TRACE_ERROR("Unknown EVPD Code: 0x%02x\n", cdb[2]);
 		return(-1);
 	}
 
-check:
-	if ((len + 4) > cmd->data_length) {
-		/*
-		 * From spc4r17 Section 4.3.5.6
-		 * If the amount of information to be transferred exceeds the
-		 * maximum value that the ALLOCATION LENGTH field is capable
-		 * of specifying, the device server shall transfer no data and
-		 * terminate the command with CHECK CONDITION status, with the
-		 * sense key set to ILLEGAL REQUEST, and the additional sense
-		 * code set to INVALID FIELD IN CDB.
-		 */
-		TRACE_ERROR("Inquiry EVPD Length: %u larger than"
-			" cmd->data_length: %u\n", (len + 4), cmd->data_length);
-		return(PYX_TRANSPORT_INVALID_CDB_FIELD);
-	}
-
 	return(0);
 }
 
-- 
1.5.4.1



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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux