Skip to content

Commit cc0b6ad

Browse files
nastya-nizharadzemartinkpetersen
authored andcommitted
scsi: target: core: Signal WRITE residuals
According to RFC 7143 11.4.5.2.: If SPDTL > EDTL for a task, iSCSI Overflow MUST be signaled in the SCSI Response PDU as specified in Section 11.4.5.1. The Residual Count MUST be set to the numerical value of (SPDTL - EDTL). If SPDTL < EDTL for a task, iSCSI Underflow MUST be signaled in the SCSI Response PDU as specified in Section 11.4.5.1. The Residual Count MUST be set to the numerical value of (EDTL - SPDTL). libiscsi has residual write tests that check residual kind and residual amount and all of them (Write10Residuals, Write12Residuals, Write16Residuals) currently fail. One of the reasons why they fail is because target completes write commands with INVALID FIELD IN CDB before setting the Overflow/Underflow bit and residual amount. Set the Overflow/Underflow bit and the residual amount before failing a write to comply with RFC 7143. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Anastasia Kovaleva <[email protected]> Signed-off-by: Roman Bolshakov <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent eb90e45 commit cc0b6ad

File tree

1 file changed

+20
-14
lines changed

1 file changed

+20
-14
lines changed

drivers/target/target_core_transport.c

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,6 +1313,26 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
13131313
" %u does not match SCSI CDB Length: %u for SAM Opcode:"
13141314
" 0x%02x\n", cmd->se_tfo->fabric_name,
13151315
cmd->data_length, size, cmd->t_task_cdb[0]);
1316+
/*
1317+
* For READ command for the overflow case keep the existing
1318+
* fabric provided ->data_length. Otherwise for the underflow
1319+
* case, reset ->data_length to the smaller SCSI expected data
1320+
* transfer length.
1321+
*/
1322+
if (size > cmd->data_length) {
1323+
cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
1324+
cmd->residual_count = (size - cmd->data_length);
1325+
} else {
1326+
cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;
1327+
cmd->residual_count = (cmd->data_length - size);
1328+
/*
1329+
* Do not truncate ->data_length for WRITE command to
1330+
* dump all payload
1331+
*/
1332+
if (cmd->data_direction == DMA_FROM_DEVICE) {
1333+
cmd->data_length = size;
1334+
}
1335+
}
13161336

13171337
if (cmd->data_direction == DMA_TO_DEVICE) {
13181338
if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
@@ -1332,20 +1352,6 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
13321352
return TCM_INVALID_CDB_FIELD;
13331353
}
13341354
}
1335-
/*
1336-
* For the overflow case keep the existing fabric provided
1337-
* ->data_length. Otherwise for the underflow case, reset
1338-
* ->data_length to the smaller SCSI expected data transfer
1339-
* length.
1340-
*/
1341-
if (size > cmd->data_length) {
1342-
cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
1343-
cmd->residual_count = (size - cmd->data_length);
1344-
} else {
1345-
cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;
1346-
cmd->residual_count = (cmd->data_length - size);
1347-
cmd->data_length = size;
1348-
}
13491355
}
13501356

13511357
return target_check_max_data_sg_nents(cmd, dev, size);

0 commit comments

Comments
 (0)