[PATCH 05/19] target: Allocate sg-list correctly

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

 



Avoid that the iSCSI target driver complains about "Initial page entry
out-of-bounds" and closes the connection if the SCSI Data-Out buffer
is larger than the buffer size specified through the CDB. This patch
prevents that running the libiscsi regression tests against LIO trigger
an infinite loop of libiscsi submitting a command, LIO closing the
connection and libiscsi resubmitting the same command.

Signed-off-by: Bart Van Assche <bart.vanassche@xxxxxxxxxxx>
Cc: Hannes Reinecke <hare@xxxxxxxx>
Cc: Christoph Hellwig <hch@xxxxxx>
Cc: Andy Grover <agrover@xxxxxxxxxx>
Cc: David Disseldorp <ddiss@xxxxxxx>
Cc: <stable@xxxxxxxxxxxxxxx>
---
 drivers/target/target_core_transport.c | 29 ++++++++++-------------------
 include/target/target_core_base.h      |  4 +++-
 2 files changed, 13 insertions(+), 20 deletions(-)

diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index df1ceb2dd110..86b6b0238975 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1159,11 +1159,11 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
 
 	if (cmd->unknown_data_length) {
 		cmd->data_length = size;
-	} else if (size != cmd->data_length) {
+	} else if (size != cmd->buffer_length) {
 		pr_warn("TARGET_CORE[%s]: Expected Transfer Length:"
 			" %u does not match SCSI CDB Length: %u for SAM Opcode:"
 			" 0x%02x\n", cmd->se_tfo->get_fabric_name(),
-				cmd->data_length, size, cmd->t_task_cdb[0]);
+			cmd->buffer_length, size, cmd->t_task_cdb[0]);
 
 		if (cmd->data_direction == DMA_TO_DEVICE &&
 		    cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
@@ -1183,7 +1183,7 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
 		}
 		/*
 		 * For the overflow case keep the existing fabric provided
-		 * ->data_length.  Otherwise for the underflow case, reset
+		 * ->buffer_length.  Otherwise for the underflow case, reset
 		 * ->data_length to the smaller SCSI expected data transfer
 		 * length.
 		 */
@@ -1227,6 +1227,7 @@ void transport_init_se_cmd(
 
 	cmd->se_tfo = tfo;
 	cmd->se_sess = se_sess;
+	cmd->buffer_length = data_length;
 	cmd->data_length = data_length;
 	cmd->data_direction = data_direction;
 	cmd->sam_task_attr = task_attr;
@@ -2412,41 +2413,31 @@ transport_generic_new_cmd(struct se_cmd *cmd)
 	 * beforehand.
 	 */
 	if (!(cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) &&
-	    cmd->data_length) {
+	    cmd->buffer_length) {
 
 		if ((cmd->se_cmd_flags & SCF_BIDI) ||
 		    (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE)) {
-			u32 bidi_length;
-
-			if (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE)
-				bidi_length = cmd->t_task_nolb *
-					      cmd->se_dev->dev_attrib.block_size;
-			else
-				bidi_length = cmd->data_length;
-
 			ret = target_alloc_sgl(&cmd->t_bidi_data_sg,
 					       &cmd->t_bidi_data_nents,
-					       bidi_length, zero_flag, false);
+					       cmd->buffer_length, zero_flag,
+					       false);
 			if (ret < 0)
 				return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 		}
 
 		ret = target_alloc_sgl(&cmd->t_data_sg, &cmd->t_data_nents,
-				       cmd->data_length, zero_flag, false);
+				       cmd->buffer_length, zero_flag, false);
 		if (ret < 0)
 			return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 	} else if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) &&
-		    cmd->data_length) {
+		    cmd->buffer_length) {
 		/*
 		 * Special case for COMPARE_AND_WRITE with fabrics
 		 * using SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC.
 		 */
-		u32 caw_length = cmd->t_task_nolb *
-				 cmd->se_dev->dev_attrib.block_size;
-
 		ret = target_alloc_sgl(&cmd->t_bidi_data_sg,
 				       &cmd->t_bidi_data_nents,
-				       caw_length, zero_flag, false);
+				       cmd->buffer_length, zero_flag, false);
 		if (ret < 0)
 			return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 	}
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 49cd03c2d943..0660585cb03d 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -455,7 +455,9 @@ struct se_cmd {
 	enum transport_state_table t_state;
 	/* See se_cmd_flags_table */
 	u32			se_cmd_flags;
-	/* Total size in bytes associated with command */
+	/* Length of Data-Out or Data-In buffer */
+	u32			buffer_length;
+	/* Number of bytes affected on storage medium */
 	u32			data_length;
 	u32			residual_count;
 	u64			orig_fe_lun;
-- 
2.12.2




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]