提交 0f69a387 编写于 作者: R Roland Dreier 提交者: Nicholas Bellinger

target: Fix handling of small allocation lengths in REPORT LUNS

REPORT LUNS should not fail just because the allocation length is less
than 16.  The relevant section of SPC-4 is:

  4.2.5.6 Allocation length

  The ALLOCATION LENGTH field specifies the maximum number of bytes or
  blocks that an application client has allocated in the Data-In
  Buffer. The ALLOCATION LENGTH field specifies bytes unless a
  different requirement is stated in the command definition.

  An allocation length of zero specifies that no data shall be
  transferred. This condition shall not be considered an error.

So we should just truncate our response rather than return an error.
Signed-off-by: NRoland Dreier <roland@purestorage.com>
Signed-off-by: NSpencer Baugh <sbaugh@catern.com>
Signed-off-by: NNicholas Bellinger <nab@linux-iscsi.org>
上级 9c395170
...@@ -1203,17 +1203,13 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd) ...@@ -1203,17 +1203,13 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
struct se_dev_entry *deve; struct se_dev_entry *deve;
struct se_session *sess = cmd->se_sess; struct se_session *sess = cmd->se_sess;
struct se_node_acl *nacl; struct se_node_acl *nacl;
struct scsi_lun slun;
unsigned char *buf; unsigned char *buf;
u32 lun_count = 0, offset = 8; u32 lun_count = 0, offset = 8;
__be32 len;
if (cmd->data_length < 16) {
pr_warn("REPORT LUNS allocation length %u too small\n",
cmd->data_length);
return TCM_INVALID_CDB_FIELD;
}
buf = transport_kmap_data_sg(cmd); buf = transport_kmap_data_sg(cmd);
if (!buf) if (cmd->data_length && !buf)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
/* /*
...@@ -1234,10 +1230,12 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd) ...@@ -1234,10 +1230,12 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
* See SPC2-R20 7.19. * See SPC2-R20 7.19.
*/ */
lun_count++; lun_count++;
if ((offset + 8) > cmd->data_length) if (offset >= cmd->data_length)
continue; continue;
int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]); int_to_scsilun(deve->mapped_lun, &slun);
memcpy(buf + offset, &slun,
min(8u, cmd->data_length - offset));
offset += 8; offset += 8;
} }
rcu_read_unlock(); rcu_read_unlock();
...@@ -1250,16 +1248,18 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd) ...@@ -1250,16 +1248,18 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
* If no LUNs are accessible, report virtual LUN 0. * If no LUNs are accessible, report virtual LUN 0.
*/ */
if (lun_count == 0) { if (lun_count == 0) {
int_to_scsilun(0, (struct scsi_lun *)&buf[offset]); int_to_scsilun(0, &slun);
if (cmd->data_length > 8)
memcpy(buf + offset, &slun,
min(8u, cmd->data_length - offset));
lun_count = 1; lun_count = 1;
} }
lun_count *= 8; if (buf) {
buf[0] = ((lun_count >> 24) & 0xff); len = cpu_to_be32(lun_count * 8);
buf[1] = ((lun_count >> 16) & 0xff); memcpy(buf, &len, min_t(int, sizeof len, cmd->data_length));
buf[2] = ((lun_count >> 8) & 0xff); transport_kunmap_data_sg(cmd);
buf[3] = (lun_count & 0xff); }
transport_kunmap_data_sg(cmd);
target_complete_cmd_with_length(cmd, GOOD, 8 + lun_count * 8); target_complete_cmd_with_length(cmd, GOOD, 8 + lun_count * 8);
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册