mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-16 02:01:27 +00:00
scst: fix tapes handling with Windows initiators
Reported and tested by Florian Gall <florian@enterprize.dyndns.info> git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@7006 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -656,8 +656,6 @@ enum scst_tg_sup {
|
||||
** Misc SCSI constants
|
||||
*************************************************************/
|
||||
#define SCST_SENSE_ASC_UA_RESET 0x29
|
||||
#define POSITION_LEN_SHORT 20
|
||||
#define POSITION_LEN_LONG 32
|
||||
|
||||
/*************************************************************
|
||||
** Compatibility constants
|
||||
|
||||
@@ -10684,8 +10684,6 @@ static int get_cdb_info_serv_act_in(struct scst_cmd *cmd,
|
||||
case SAI_READ_CAPACITY_16:
|
||||
cmd->op_name = "READ CAPACITY(16)";
|
||||
cmd->bufflen = get_unaligned_be32(&cmd->cdb[10]);
|
||||
if (unlikely(cmd->bufflen & SCST_MAX_VALID_BUFFLEN_MASK))
|
||||
goto out_inval_bufflen10;
|
||||
cmd->op_flags |= SCST_IMPLICIT_HQ | SCST_LBA_NOT_VALID |
|
||||
SCST_REG_RESERVE_ALLOWED |
|
||||
SCST_WRITE_EXCL_ALLOWED |
|
||||
@@ -10695,8 +10693,6 @@ static int get_cdb_info_serv_act_in(struct scst_cmd *cmd,
|
||||
cmd->op_name = "GET LBA STATUS";
|
||||
cmd->lba = get_unaligned_be64(&cmd->cdb[2]);
|
||||
cmd->bufflen = get_unaligned_be32(&cmd->cdb[10]);
|
||||
if (unlikely(cmd->bufflen & SCST_MAX_VALID_BUFFLEN_MASK))
|
||||
goto out_inval_bufflen10;
|
||||
cmd->op_flags |= SCST_WRITE_EXCL_ALLOWED;
|
||||
break;
|
||||
default:
|
||||
@@ -10706,16 +10702,8 @@ static int get_cdb_info_serv_act_in(struct scst_cmd *cmd,
|
||||
|
||||
cmd->data_len = cmd->bufflen;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
out_inval_bufflen10:
|
||||
PRINT_ERROR("Too big bufflen %d (op %s)", cmd->bufflen,
|
||||
scst_get_opcode_name(cmd));
|
||||
scst_set_invalid_field_in_cdb(cmd, 10, 0);
|
||||
res = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int get_cdb_info_single(struct scst_cmd *cmd,
|
||||
@@ -10738,19 +10726,6 @@ static int get_cdb_info_read_pos(struct scst_cmd *cmd,
|
||||
|
||||
cmd->bufflen = get_unaligned_be16(cmd->cdb + sdbops->info_len_off);
|
||||
|
||||
switch (cmd->cdb[1] & 0x1f) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 6:
|
||||
if (cmd->bufflen != 0) {
|
||||
PRINT_ERROR("READ POSITION: Invalid non-zero (%d) "
|
||||
"allocation length for service action %x",
|
||||
cmd->bufflen, cmd->cdb[1] & 0x1f);
|
||||
goto out_inval_field1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cmd->cdb[1] & 0x1f) {
|
||||
case 0:
|
||||
case 1:
|
||||
@@ -10913,12 +10888,6 @@ static int get_cdb_info_verify12(struct scst_cmd *cmd,
|
||||
cmd->lba = get_unaligned_be32(cmd->cdb + sdbops->info_lba_off);
|
||||
if (cmd->cdb[1] & 2) { /* BYTCHK 01 */
|
||||
cmd->bufflen = get_unaligned_be32(cmd->cdb + sdbops->info_len_off);
|
||||
if (unlikely(cmd->bufflen & SCST_MAX_VALID_BUFFLEN_MASK)) {
|
||||
PRINT_ERROR("Too big bufflen %d (op %s)",
|
||||
cmd->bufflen, scst_get_opcode_name(cmd));
|
||||
scst_set_invalid_field_in_cdb(cmd, sdbops->info_len_off, 0);
|
||||
return 1;
|
||||
}
|
||||
cmd->data_len = cmd->bufflen;
|
||||
cmd->data_direction = SCST_DATA_WRITE;
|
||||
} else {
|
||||
@@ -10943,12 +10912,6 @@ static int get_cdb_info_verify16(struct scst_cmd *cmd,
|
||||
cmd->lba = get_unaligned_be64(cmd->cdb + sdbops->info_lba_off);
|
||||
if (cmd->cdb[1] & 2) { /* BYTCHK 01 */
|
||||
cmd->bufflen = get_unaligned_be32(cmd->cdb + sdbops->info_len_off);
|
||||
if (unlikely(cmd->bufflen & SCST_MAX_VALID_BUFFLEN_MASK)) {
|
||||
PRINT_ERROR("Too big bufflen %d (op %s)",
|
||||
cmd->bufflen, scst_get_opcode_name(cmd));
|
||||
scst_set_invalid_field_in_cdb(cmd, sdbops->info_len_off, 0);
|
||||
return 1;
|
||||
}
|
||||
cmd->data_len = cmd->bufflen;
|
||||
cmd->data_direction = SCST_DATA_WRITE;
|
||||
} else {
|
||||
@@ -10973,12 +10936,6 @@ static int get_cdb_info_verify32(struct scst_cmd *cmd,
|
||||
cmd->lba = get_unaligned_be64(cmd->cdb + sdbops->info_lba_off);
|
||||
if (cmd->cdb[10] & 2) {
|
||||
cmd->bufflen = get_unaligned_be32(cmd->cdb + sdbops->info_len_off);
|
||||
if (unlikely(cmd->bufflen & SCST_MAX_VALID_BUFFLEN_MASK)) {
|
||||
PRINT_ERROR("Too big bufflen %d (op %s)",
|
||||
cmd->bufflen, scst_get_opcode_name(cmd));
|
||||
scst_set_invalid_field_in_cdb(cmd, sdbops->info_len_off, 0);
|
||||
return 1;
|
||||
}
|
||||
cmd->data_len = cmd->bufflen;
|
||||
cmd->data_direction = SCST_DATA_WRITE;
|
||||
} else {
|
||||
@@ -11085,12 +11042,6 @@ static int get_cdb_info_len_4(struct scst_cmd *cmd,
|
||||
cmd->op_flags |= SCST_LBA_NOT_VALID;
|
||||
cmd->lba = 0;
|
||||
cmd->bufflen = get_unaligned_be32(cmd->cdb + sdbops->info_len_off);
|
||||
if (unlikely(cmd->bufflen & SCST_MAX_VALID_BUFFLEN_MASK)) {
|
||||
PRINT_ERROR("Too big bufflen %d (op %s)", cmd->bufflen,
|
||||
scst_get_opcode_name(cmd));
|
||||
scst_set_invalid_field_in_cdb(cmd, sdbops->info_len_off, 0);
|
||||
return 1;
|
||||
}
|
||||
cmd->data_len = cmd->bufflen;
|
||||
return 0;
|
||||
}
|
||||
@@ -11185,12 +11136,6 @@ static inline int get_cdb_info_lba_4_len_4(struct scst_cmd *cmd,
|
||||
{
|
||||
cmd->lba = get_unaligned_be32(cmd->cdb + sdbops->info_lba_off);
|
||||
cmd->bufflen = get_unaligned_be32(cmd->cdb + sdbops->info_len_off);
|
||||
if (unlikely(cmd->bufflen & SCST_MAX_VALID_BUFFLEN_MASK)) {
|
||||
PRINT_ERROR("Too big bufflen %d (op %s)", cmd->bufflen,
|
||||
scst_get_opcode_name(cmd));
|
||||
scst_set_invalid_field_in_cdb(cmd, sdbops->info_len_off, 0);
|
||||
return 1;
|
||||
}
|
||||
cmd->data_len = cmd->bufflen;
|
||||
return 0;
|
||||
}
|
||||
@@ -11222,12 +11167,6 @@ static inline int get_cdb_info_lba_8_len_4(struct scst_cmd *cmd,
|
||||
{
|
||||
cmd->lba = get_unaligned_be64(cmd->cdb + sdbops->info_lba_off);
|
||||
cmd->bufflen = get_unaligned_be32(cmd->cdb + sdbops->info_len_off);
|
||||
if (unlikely(cmd->bufflen & SCST_MAX_VALID_BUFFLEN_MASK)) {
|
||||
PRINT_ERROR("Too big bufflen %d (op %s)", cmd->bufflen,
|
||||
scst_get_opcode_name(cmd));
|
||||
scst_set_invalid_field_in_cdb(cmd, sdbops->info_len_off, 0);
|
||||
return 1;
|
||||
}
|
||||
cmd->data_len = cmd->bufflen;
|
||||
return 0;
|
||||
}
|
||||
@@ -11956,28 +11895,30 @@ int scst_tape_generic_parse(struct scst_cmd *cmd)
|
||||
* therefore change them only if necessary
|
||||
*/
|
||||
|
||||
if (cmd->cdb[0] == READ_POSITION) {
|
||||
int tclp = cmd->cdb[1] & 4;
|
||||
int long_bit = cmd->cdb[1] & 2;
|
||||
int bt = cmd->cdb[1] & 1;
|
||||
|
||||
if ((tclp == long_bit) && (!bt || !long_bit)) {
|
||||
cmd->bufflen =
|
||||
tclp ? POSITION_LEN_LONG : POSITION_LEN_SHORT;
|
||||
cmd->data_direction = SCST_DATA_READ;
|
||||
} else {
|
||||
cmd->bufflen = 0;
|
||||
cmd->data_direction = SCST_DATA_NONE;
|
||||
}
|
||||
cmd->data_len = cmd->bufflen;
|
||||
}
|
||||
|
||||
if (cmd->op_flags & SCST_TRANSFER_LEN_TYPE_FIXED && cmd->cdb[1] & 1) {
|
||||
int block_size = cmd->dev->block_size;
|
||||
unsigned int ob = cmd->bufflen, od = cmd->data_len, oo = cmd->out_bufflen;
|
||||
bool overflow;
|
||||
|
||||
cmd->bufflen = cmd->bufflen * block_size;
|
||||
cmd->data_len = cmd->data_len * block_size;
|
||||
cmd->out_bufflen = cmd->out_bufflen * block_size;
|
||||
|
||||
overflow = (ob < (unsigned int)cmd->bufflen) ||
|
||||
(od < (unsigned int)cmd->data_len) ||
|
||||
(oo < (unsigned int)cmd->out_bufflen);
|
||||
if (unlikely(overflow)) {
|
||||
PRINT_WARNING("bufflen %u, data_len %llu or out_bufflen"
|
||||
" %u too large for device %s (block size"
|
||||
" %u)", cmd->bufflen, cmd->data_len,
|
||||
cmd->out_bufflen, cmd->dev->virt_name,
|
||||
block_size);
|
||||
PRINT_BUFFER("CDB", cmd->cdb, cmd->cdb_len);
|
||||
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
|
||||
scst_sense_block_out_range_error));
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if ((cmd->op_flags & (SCST_SMALL_TIMEOUT | SCST_LONG_TIMEOUT)) == 0)
|
||||
@@ -11987,6 +11928,7 @@ int scst_tape_generic_parse(struct scst_cmd *cmd)
|
||||
else if (cmd->op_flags & SCST_LONG_TIMEOUT)
|
||||
cmd->timeout = SCST_GENERIC_TAPE_LONG_TIMEOUT;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user