Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: 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.

Signed-off-by: Bodo Stroesser <bstroesser@ts.fujitsu.com>
Signed-off-by: Lee Duncan <lduncan@suse.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Lee Duncan and committed by
Martin K. Petersen
bd813720 51b910c3

+62 -8
+24 -2
drivers/target/target_core_pscsi.c
··· 689 689 } 690 690 after_mode_select: 691 691 692 - if (scsi_status == SAM_STAT_CHECK_CONDITION) 692 + if (scsi_status == SAM_STAT_CHECK_CONDITION) { 693 693 transport_copy_sense_to_cmd(cmd, req_sense); 694 + 695 + /* 696 + * check for TAPE device reads with 697 + * FM/EOM/ILI set, so that we can get data 698 + * back despite framework assumption that a 699 + * check condition means there is no data 700 + */ 701 + if (sd->type == TYPE_TAPE && 702 + cmd->data_direction == DMA_FROM_DEVICE) { 703 + /* 704 + * is sense data valid, fixed format, 705 + * and have FM, EOM, or ILI set? 706 + */ 707 + if (req_sense[0] == 0xf0 && /* valid, fixed format */ 708 + req_sense[2] & 0xe0 && /* FM, EOM, or ILI */ 709 + (req_sense[2] & 0xf) == 0) { /* key==NO_SENSE */ 710 + pr_debug("Tape FM/EOM/ILI status detected. Treat as normal read.\n"); 711 + cmd->se_cmd_flags |= SCF_TREAT_READ_AS_NORMAL; 712 + } 713 + } 714 + } 694 715 } 695 716 696 717 enum { ··· 1082 1061 1083 1062 switch (host_byte(result)) { 1084 1063 case DID_OK: 1085 - target_complete_cmd(cmd, scsi_status); 1064 + target_complete_cmd_with_length(cmd, scsi_status, 1065 + cmd->data_length - scsi_req(req)->resid_len); 1086 1066 break; 1087 1067 default: 1088 1068 pr_debug("PSCSI Host Byte exception at cmd: %p CDB:"
+37 -6
drivers/target/target_core_transport.c
··· 779 779 780 780 void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length) 781 781 { 782 - if (scsi_status == SAM_STAT_GOOD && length < cmd->data_length) { 782 + if ((scsi_status == SAM_STAT_GOOD || 783 + cmd->se_cmd_flags & SCF_TREAT_READ_AS_NORMAL) && 784 + length < cmd->data_length) { 783 785 if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) { 784 786 cmd->residual_count += cmd->data_length - length; 785 787 } else { ··· 2086 2084 goto queue_status; 2087 2085 } 2088 2086 2089 - if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) 2087 + /* 2088 + * Check if we need to send a sense buffer from 2089 + * the struct se_cmd in question. We do NOT want 2090 + * to take this path of the IO has been marked as 2091 + * needing to be treated like a "normal read". This 2092 + * is the case if it's a tape read, and either the 2093 + * FM, EOM, or ILI bits are set, but there is no 2094 + * sense data. 2095 + */ 2096 + if (!(cmd->se_cmd_flags & SCF_TREAT_READ_AS_NORMAL) && 2097 + cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) 2090 2098 goto queue_status; 2091 2099 2092 2100 switch (cmd->data_direction) { 2093 2101 case DMA_FROM_DEVICE: 2094 - if (cmd->scsi_status) 2102 + /* queue status if not treating this as a normal read */ 2103 + if (cmd->scsi_status && 2104 + !(cmd->se_cmd_flags & SCF_TREAT_READ_AS_NORMAL)) 2095 2105 goto queue_status; 2096 2106 2097 2107 trace_target_cmd_complete(cmd); ··· 2208 2194 2209 2195 /* 2210 2196 * Check if we need to send a sense buffer from 2211 - * the struct se_cmd in question. 2197 + * the struct se_cmd in question. We do NOT want 2198 + * to take this path of the IO has been marked as 2199 + * needing to be treated like a "normal read". This 2200 + * is the case if it's a tape read, and either the 2201 + * FM, EOM, or ILI bits are set, but there is no 2202 + * sense data. 2212 2203 */ 2213 - if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { 2204 + if (!(cmd->se_cmd_flags & SCF_TREAT_READ_AS_NORMAL) && 2205 + cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { 2214 2206 WARN_ON(!cmd->scsi_status); 2215 2207 ret = transport_send_check_condition_and_sense( 2216 2208 cmd, 0, 1); ··· 2258 2238 queue_rsp: 2259 2239 switch (cmd->data_direction) { 2260 2240 case DMA_FROM_DEVICE: 2261 - if (cmd->scsi_status) 2241 + /* 2242 + * if this is a READ-type IO, but SCSI status 2243 + * is set, then skip returning data and just 2244 + * return the status -- unless this IO is marked 2245 + * as needing to be treated as a normal read, 2246 + * in which case we want to go ahead and return 2247 + * the data. This happens, for example, for tape 2248 + * reads with the FM, EOM, or ILI bits set, with 2249 + * no sense data. 2250 + */ 2251 + if (cmd->scsi_status && 2252 + !(cmd->se_cmd_flags & SCF_TREAT_READ_AS_NORMAL)) 2262 2253 goto queue_status; 2263 2254 2264 2255 atomic_long_add(cmd->data_length,
+1
include/target/target_core_base.h
··· 143 143 SCF_ACK_KREF = 0x00400000, 144 144 SCF_USE_CPUID = 0x00800000, 145 145 SCF_TASK_ATTR_SET = 0x01000000, 146 + SCF_TREAT_READ_AS_NORMAL = 0x02000000, 146 147 }; 147 148 148 149 /*