From 293c2f3abdda8c64cbd132641cacf7b0745e6439 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Wed, 15 Feb 2012 22:32:05 +0000 Subject: [PATCH] Slightly modified patch from Bart Van Assche cleaning VERIFY commands processing git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4131 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- doc/scst_user_spec.sgml | 3 - scst/include/scst_const.h | 1 - scst/src/dev_handlers/scst_vdisk.c | 35 ++++++++---- scst/src/scst_lib.c | 91 ++++++++++++++++++++++-------- scst/src/scst_targ.c | 8 --- 5 files changed, 93 insertions(+), 45 deletions(-) diff --git a/doc/scst_user_spec.sgml b/doc/scst_user_spec.sgml index 650a3e569..f6ad09287 100644 --- a/doc/scst_user_spec.sgml +++ b/doc/scst_user_spec.sgml @@ -767,9 +767,6 @@ Bits of scst_cdb_flags can be: bufflen; break; case READ_16: case WRITE_16: case WRITE_VERIFY_16: - case VERIFY_16: lba_start = get_unaligned_be64(&cdb[2]); data_len = cmd->bufflen; break; + case VERIFY: + lba_start = get_unaligned_be32(&cdb[2]); + data_len = get_unaligned_be16(&cdb[7]) << virt_dev->block_shift; + break; + case VERIFY_12: + lba_start = get_unaligned_be32(&cdb[2]); + data_len = get_unaligned_be32(&cdb[6]) << virt_dev->block_shift; + break; + case VERIFY_16: + lba_start = get_unaligned_be64(&cdb[2]); + data_len = get_unaligned_be32(&cdb[10]) << virt_dev->block_shift; + break; case SYNCHRONIZE_CACHE: lba_start = get_unaligned_be32(&cdb[2]); data_len = get_unaligned_be16(&cdb[7]) << virt_dev->block_shift; @@ -3364,6 +3373,10 @@ static enum compl_status_e fileio_exec_verify(struct vdisk_cmd_params *p) * from the file/disk yet. */ + compare = scst_cmd_get_data_direction(cmd) == SCST_DATA_WRITE; + TRACE_DBG("VERIFY with BYTCHK=%d at offset %lld and with len = %lld\n", + compare, loff, p->data_len); + /* SEEK */ old_fs = get_fs(); set_fs(get_ds()); @@ -3392,13 +3405,12 @@ static enum compl_status_e fileio_exec_verify(struct vdisk_cmd_params *p) goto out_set_fs; } - length = scst_get_buf_first(cmd, &address); - address_sav = address; - if (!length && cmd->data_len) { - length = cmd->data_len; - compare = 0; - } else - compare = 1; + if (compare) { + length = scst_get_buf_first(cmd, &address); + address_sav = address; + } else { + length = p->data_len; + } while (length > 0) { len_mem = (length > LEN_MEM) ? LEN_MEM : length; @@ -3430,7 +3442,8 @@ static enum compl_status_e fileio_exec_verify(struct vdisk_cmd_params *p) goto out_set_fs; } length -= len_mem; - address += len_mem; + if (compare) + address += len_mem; if (compare && length <= 0) { scst_put_buf(cmd, address_sav); length = scst_get_buf_next(cmd, &address); diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 3dbe6e78c..c39a2aab3 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -76,6 +76,10 @@ static int get_trans_len_4(struct scst_cmd *cmd, uint8_t off); static int get_bidi_trans_len_2(struct scst_cmd *cmd, uint8_t off); +static int get_verify_trans_len_2(struct scst_cmd *cmd, uint8_t off); +static int get_verify_trans_len_3(struct scst_cmd *cmd, uint8_t off); +static int get_verify_trans_len_4(struct scst_cmd *cmd, uint8_t off); + /* for special commands */ static int get_trans_len_block_limit(struct scst_cmd *cmd, uint8_t off); static int get_trans_len_read_capacity(struct scst_cmd *cmd, uint8_t off); @@ -262,10 +266,9 @@ static const struct scst_sdbops scst_scsi_op_table[] = { SCST_WRITE_EXCL_ALLOWED|SCST_EXCL_ACCESS_ALLOWED, 3, get_trans_len_2}, {0x13, "VOVVVV ", "VERIFY(6)", - SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED| - SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED| - SCST_WRITE_EXCL_ALLOWED, - 2, get_trans_len_3}, + SCST_DATA_UNKNOWN, SCST_TRANSFER_LEN_TYPE_FIXED| + SCST_WRITE_EXCL_ALLOWED, + 2, get_verify_trans_len_3}, {0x14, "VOOVVV ", "RECOVER BUFFERED DATA", SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED| SCST_WRITE_EXCL_ALLOWED, @@ -358,10 +361,9 @@ static const struct scst_sdbops scst_scsi_op_table[] = { SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM, 7, get_trans_len_2}, {0x2F, "O OO O ", "VERIFY(10)", - SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED| - SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED| - SCST_WRITE_EXCL_ALLOWED, - 7, get_trans_len_2}, + SCST_DATA_UNKNOWN, SCST_TRANSFER_LEN_TYPE_FIXED| + SCST_WRITE_EXCL_ALLOWED, + 7, get_verify_trans_len_2}, {0x33, "O OO O ", "SET LIMITS(10)", SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none}, {0x34, " O ", "READ POSITION", @@ -537,10 +539,9 @@ static const struct scst_sdbops scst_scsi_op_table[] = { SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM, 10, get_trans_len_4}, {0x8F, "O OO O ", "VERIFY(16)", - SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED| - SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED| - SCST_WRITE_EXCL_ALLOWED, - 10, get_trans_len_4}, + SCST_DATA_UNKNOWN, SCST_TRANSFER_LEN_TYPE_FIXED| + SCST_WRITE_EXCL_ALLOWED, + 10, get_verify_trans_len_4}, {0x90, "O OO O ", "PRE-FETCH(16)", SCST_DATA_NONE, SCST_WRITE_EXCL_ALLOWED, 0, get_trans_len_none}, @@ -624,10 +625,9 @@ static const struct scst_sdbops scst_scsi_op_table[] = { SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM, 6, get_trans_len_4}, {0xAF, "O OO O ", "VERIFY(12)", - SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED| - SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED| - SCST_WRITE_EXCL_ALLOWED, - 6, get_trans_len_4}, + SCST_DATA_UNKNOWN, SCST_TRANSFER_LEN_TYPE_FIXED| + SCST_WRITE_EXCL_ALLOWED, + 6, get_verify_trans_len_4}, #if 0 /* No need to support at all */ {0xB0, " OO O ", "SEARCH DATA HIGH(12)", SCST_DATA_WRITE, FLAG_NONE, 9, get_trans_len_1}, @@ -5116,6 +5116,59 @@ static int get_trans_len_3_read_elem_stat(struct scst_cmd *cmd, uint8_t off) return 0; } +static int get_bidi_trans_len_2(struct scst_cmd *cmd, uint8_t off) +{ + cmd->bufflen = get_unaligned_be16(cmd->cdb + off); + cmd->out_bufflen = cmd->bufflen; + return 0; +} + +/* + * get_verify_trans_len_2() - Compute transport len and dir for SCSI VERIFY. + * + * Whether a data-out buffer is associated with a SCSI VERIFY command depends on + * the BYTCHK bit in that command. Check that bit and compute the data out + * buffer length and the data transfer direction. + */ +static int get_verify_trans_len_2(struct scst_cmd *cmd, uint8_t off) +{ + if (cmd->cdb[1] & BYTCHK) { + cmd->bufflen = get_unaligned_be16(cmd->cdb + off); + cmd->data_direction = SCST_DATA_WRITE; + } else { + cmd->bufflen = 0; + cmd->data_direction = SCST_DATA_NONE; + } + + return 0; +} + +static int get_verify_trans_len_3(struct scst_cmd *cmd, uint8_t off) +{ + if (cmd->cdb[1] & BYTCHK) { + cmd->bufflen = get_unaligned_be24(cmd->cdb + off); + cmd->data_direction = SCST_DATA_WRITE; + } else { + cmd->bufflen = 0; + cmd->data_direction = SCST_DATA_NONE; + } + + return 0; +} + +static int get_verify_trans_len_4(struct scst_cmd *cmd, uint8_t off) +{ + if (cmd->cdb[1] & BYTCHK) { + cmd->bufflen = get_unaligned_be32(cmd->cdb + off); + cmd->data_direction = SCST_DATA_WRITE; + } else { + cmd->bufflen = 0; + cmd->data_direction = SCST_DATA_NONE; + } + + return 0; +} + static int get_trans_len_1(struct scst_cmd *cmd, uint8_t off) { cmd->bufflen = (u32)cmd->cdb[off]; @@ -5164,12 +5217,6 @@ static int get_trans_len_none(struct scst_cmd *cmd, uint8_t off) return 0; } -static int get_bidi_trans_len_2(struct scst_cmd *cmd, uint8_t off) -{ - cmd->bufflen = get_unaligned_be16(cmd->cdb + off); - cmd->out_bufflen = cmd->bufflen; - return 0; -} /** * scst_get_cdb_info() - fill various info about the command's CDB diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 0488cfe31..17b910e3a 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -532,13 +532,6 @@ static bool scst_is_allowed_to_mismatch_cmd(struct scst_cmd *cmd) { bool res = false; - /* VERIFY commands with BYTCHK unset shouldn't fail here */ - if ((cmd->op_flags & SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED) && - (cmd->cdb[1] & BYTCHK) == 0) { - res = true; - goto out; - } - switch (cmd->cdb[0]) { case TEST_UNIT_READY: /* Crazy VMware people sometimes do TUR with READ direction */ @@ -548,7 +541,6 @@ static bool scst_is_allowed_to_mismatch_cmd(struct scst_cmd *cmd) break; } -out: return res; } #endif