Skip to content

Commit

Permalink
target: Fix residual overflow handling in target_complete_cmd_with_le…
Browse files Browse the repository at this point in the history
…ngth

This patch fixes residual overflow handling to correctly set the
residual_count using SPDTL, instead of SCSI Allocation Length.

Allocation Length is the maximum value of the SPDTL and not substitute
for it, hence it shouldn’t be used to calculate ResidualCount except for
cases where SPDTL > Allocation Length and Data is truncated (in that
case both Alloc Len and SPDTL are same). (SPC 5r01 Section 4.2.5.6).

Thanks to Ajay Nair in assisting with this patch.

Signed-off-by: Sumit Rai <sumitrai96@gmail.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
  • Loading branch information
Sumit Rai authored and Nicholas Bellinger committed Jul 24, 2016
1 parent 107818e commit c1ccbfe
Showing 1 changed file with 15 additions and 1 deletion.
16 changes: 15 additions & 1 deletion drivers/target/target_core_transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,15 @@ EXPORT_SYMBOL(target_complete_cmd);

void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length)
{
if (scsi_status == SAM_STAT_GOOD && length < cmd->data_length) {
if (scsi_status != SAM_STAT_GOOD) {
return;
}

/*
* Calculate new residual count based upon length of SCSI data
* transferred.
*/
if (length < cmd->data_length) {
if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
cmd->residual_count += cmd->data_length - length;
} else {
Expand All @@ -763,6 +771,12 @@ void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int len
}

cmd->data_length = length;
} else if (length > cmd->data_length) {
cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
cmd->residual_count = length - cmd->data_length;
} else {
cmd->se_cmd_flags &= ~(SCF_OVERFLOW_BIT | SCF_UNDERFLOW_BIT);
cmd->residual_count = 0;
}

target_complete_cmd(cmd, scsi_status);
Expand Down

0 comments on commit c1ccbfe

Please sign in to comment.