aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSagi Grimberg <sagig@mellanox.com>2014-06-11 05:09:59 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2014-06-11 16:06:50 -0400
commite2a4f55c6498b59a17a85a1bb6db122a993ffe02 (patch)
tree8532312775b3245206db6a91f1d83621f55275df
parentd77e65350f2d82dfa0557707d505711f5a43c8fd (diff)
TARGET/sbc,loopback: Adjust command data length in case pi exists on the wire
In various areas of the code, it is assumed that se_cmd->data_length describes pure data. In case that protection information exists over the wire (protect bits is are on) the target core re-calculates the data length from the CDB and the backed device block size (instead of each transport peeking in the cdb). Modify loopback device to include protection information in the transferred data length (like other scsi transports). Signed-off-by: Sagi Grimberg <sagig@mellanox.com> Cc: stable@vger.kernel.org # 3.15+ Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/target/loopback/tcm_loop.c15
-rw-r--r--drivers/target/target_core_sbc.c15
2 files changed, 25 insertions, 5 deletions
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index c886ad1c39fb..1f4c015e9078 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -179,7 +179,7 @@ static void tcm_loop_submission_work(struct work_struct *work)
179 struct tcm_loop_hba *tl_hba; 179 struct tcm_loop_hba *tl_hba;
180 struct tcm_loop_tpg *tl_tpg; 180 struct tcm_loop_tpg *tl_tpg;
181 struct scatterlist *sgl_bidi = NULL; 181 struct scatterlist *sgl_bidi = NULL;
182 u32 sgl_bidi_count = 0; 182 u32 sgl_bidi_count = 0, transfer_length;
183 int rc; 183 int rc;
184 184
185 tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); 185 tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
@@ -213,12 +213,21 @@ static void tcm_loop_submission_work(struct work_struct *work)
213 213
214 } 214 }
215 215
216 if (!scsi_prot_sg_count(sc) && scsi_get_prot_op(sc) != SCSI_PROT_NORMAL) 216 transfer_length = scsi_transfer_length(sc);
217 if (!scsi_prot_sg_count(sc) &&
218 scsi_get_prot_op(sc) != SCSI_PROT_NORMAL) {
217 se_cmd->prot_pto = true; 219 se_cmd->prot_pto = true;
220 /*
221 * loopback transport doesn't support
222 * WRITE_GENERATE, READ_STRIP protection
223 * information operations, go ahead unprotected.
224 */
225 transfer_length = scsi_bufflen(sc);
226 }
218 227
219 rc = target_submit_cmd_map_sgls(se_cmd, tl_nexus->se_sess, sc->cmnd, 228 rc = target_submit_cmd_map_sgls(se_cmd, tl_nexus->se_sess, sc->cmnd,
220 &tl_cmd->tl_sense_buf[0], tl_cmd->sc->device->lun, 229 &tl_cmd->tl_sense_buf[0], tl_cmd->sc->device->lun,
221 scsi_bufflen(sc), tcm_loop_sam_attr(sc), 230 transfer_length, tcm_loop_sam_attr(sc),
222 sc->sc_data_direction, 0, 231 sc->sc_data_direction, 0,
223 scsi_sglist(sc), scsi_sg_count(sc), 232 scsi_sglist(sc), scsi_sg_count(sc),
224 sgl_bidi, sgl_bidi_count, 233 sgl_bidi, sgl_bidi_count,
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index 1d3a626bf24f..bd78d9235ac6 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -647,8 +647,19 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
647 647
648 cmd->prot_type = dev->dev_attrib.pi_prot_type; 648 cmd->prot_type = dev->dev_attrib.pi_prot_type;
649 cmd->prot_length = dev->prot_length * sectors; 649 cmd->prot_length = dev->prot_length * sectors;
650 pr_debug("%s: prot_type=%d, prot_length=%d prot_op=%d prot_checks=%d\n", 650
651 __func__, cmd->prot_type, cmd->prot_length, 651 /**
652 * In case protection information exists over the wire
653 * we modify command data length to describe pure data.
654 * The actual transfer length is data length + protection
655 * length
656 **/
657 if (protect)
658 cmd->data_length = sectors * dev->dev_attrib.block_size;
659
660 pr_debug("%s: prot_type=%d, data_length=%d, prot_length=%d "
661 "prot_op=%d prot_checks=%d\n",
662 __func__, cmd->prot_type, cmd->data_length, cmd->prot_length,
652 cmd->prot_op, cmd->prot_checks); 663 cmd->prot_op, cmd->prot_checks);
653 664
654 return true; 665 return true;