target: transport should handle st FM/EOM/ILI reads
PATCH v4 1/1 target: transport should handle st FM/EOM/ILI reads
When a tape drive is exported via LIO using the pscsi module, a read that requests more bytes per block than the tape can supply returns an empty buffer. This is because the pscsi pass-through target module sees the "ILI" illegal length bit set and thinks there is no reason to return the data.
This is a long-standing transport issue, since it assumes that no data need be returned under a check condition, which isn't always the case for tape.
Add in a check for tape reads with the ILI, EOM, or FM bits set, with a sense code of NO_SENSE, treating such cases as if the read succeeded. The layered tape driver then "does the right thing" when it gets such a response.
Changes from v3:
- cleaned up comment
- Added residual handling
Changes from v2:
- Cleaned up subject line and bug text formatting
- Removed unneeded inner braces
- Removed ugly goto
- Also updated the "queue full" path to handle this case
Changes from RFC:
- Moved ugly code from transport to pscsi module
- Added checking EOM and FM bits, as well as ILI
- fixed malformed patch
- Clarified description a bit
--- drivers/target/target_core_pscsi.c | 26 ++++++++++++++++++-- drivers/target/target_core_transport.c | 43 +++++++++++++++++++++++++++++----- include/target/target_core_base.h | 1 + 3 files changed, 62 insertions(+), 8 deletions(-)
drivers/target/target_core_pscsi.c +24 -2
@@ -689,8 +689,29 @@ static void pscsi_complete_cmd(struct se_cmd *cmd, u8 scsi_status, } after_mode_select: -if (scsi_status =SAM_STAT_CHECK_CONDITION ) +if (scsi_status =SAM_STAT_CHECK_CONDITION ) {transport_copy_sense_to_cmd (cmd, req_sense); + +/* +* check for TAPE device reads with +* FM/EOM/ILI set, so that we can get data +* back despite framework assumption that a +* check condition means there is no data +*/ +if (sd->type =TYPE_TAPE && + cmd->data_direction =DMA_FROM_DEVICE ) { +/* +* is sense data valid, fixed format, +* and have FM, EOM, or ILI set? +*/ +if (req_sense[0 ] =0xf0 &&/* valid, fixed format */ + req_sense[2 ] &0xe0 &&/* FM, EOM, or ILI */ + (req_sense[2 ] &0xf ) =0 ) {/* key=NO_SENSE */ +pr_debug ("Tape FM/EOM/ILI status detected. Treat as normal read.\n" ); + cmd->se_cmd_flags |=SCF_TREAT_READ_AS_NORMAL ; + } + } + } }enum {
@@ -1061,7 +1082,8 @@ static void pscsi_req_done(struct request *req, blk_status_t status)switch (host_byte (result)) {case DID_OK : -target_complete_cmd (cmd, scsi_status); +target_complete_cmd_with_length (cmd, scsi_status, + cmd->data_length -scsi_req (req)->resid_len);break ;default : pr_debug("PSCSI Host Byte exception at cmd: %p CDB:"
drivers/target/target_core_transport.c +37 -6
72 lines not on this page · raw message
include/target/target_core_base.h +1 -0
@@ -143,6 +143,7 @@ enum se_cmd_flags_table {SCF_ACK_KREF =0x00400000 ,SCF_USE_CPUID =0x00800000 ,SCF_TASK_ATTR_SET =0x01000000 , + SCF_TREAT_READ_AS_NORMAL = 0x02000000, };/*
Signature · 1 line
2.13.6
Martin K. Petersen
AppliedLee,
Quoted 5 lines
When a tape drive is exported via LIO using the pscsi module, a read that requests more bytes per block than the tape can supply returns an empty buffer. This is because the pscsi pass-through target module sees the "ILI" illegal length bit set and thinks there is no reason to return the data.
Applied to 4.18/scsi-queue. Thank you!
Signature · 1 line
Martin K. Petersen Oracle Linux Engineering