target: Report correct response length for some commands

When an initiator sends an allocation length bigger than what its
command consumes, the target should only return the actual response data
and set the residual length to the unused part of the allocation length.

Add a helper function that command handlers (INQUIRY, READ CAPACITY,
etc) can use to do this correctly, and use this code to get the correct
residual for commands that don't use the full initiator allocation in the
handlers for READ CAPACITY, READ CAPACITY(16), INQUIRY, MODE SENSE and
REPORT LUNS.

This addresses a handful of failures as reported by Christophe with
the Windows Certification Kit:

  http://permalink.gmane.org/gmane.linux.scsi.target.devel/6515

Signed-off-by: Roland Dreier <roland@purestorage.com>
Tested-by: Christophe Vu-Brugier <cvubrugier@yahoo.fr>
Cc: stable@vger.kernel.org # 3.10+
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
Roland Dreier
2014-06-10 11:07:47 -07:00
committed by Nicholas Bellinger
parent c52716defd
commit 2426bd456a
4 changed files with 26 additions and 5 deletions

View File

@@ -716,6 +716,7 @@ spc_emulate_inquiry(struct se_cmd *cmd)
unsigned char *buf;
sense_reason_t ret;
int p;
int len = 0;
buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL);
if (!buf) {
@@ -737,6 +738,7 @@ spc_emulate_inquiry(struct se_cmd *cmd)
}
ret = spc_emulate_inquiry_std(cmd, buf);
len = buf[4] + 5;
goto out;
}
@@ -744,6 +746,7 @@ spc_emulate_inquiry(struct se_cmd *cmd)
if (cdb[2] == evpd_handlers[p].page) {
buf[1] = cdb[2];
ret = evpd_handlers[p].emulate(cmd, buf);
len = get_unaligned_be16(&buf[2]) + 4;
goto out;
}
}
@@ -760,7 +763,7 @@ out:
kfree(buf);
if (!ret)
target_complete_cmd(cmd, GOOD);
target_complete_cmd_with_length(cmd, GOOD, len);
return ret;
}
@@ -1098,7 +1101,7 @@ set_length:
transport_kunmap_data_sg(cmd);
}
target_complete_cmd(cmd, GOOD);
target_complete_cmd_with_length(cmd, GOOD, length);
return 0;
}
@@ -1274,7 +1277,7 @@ done:
buf[3] = (lun_count & 0xff);
transport_kunmap_data_sg(cmd);
target_complete_cmd(cmd, GOOD);
target_complete_cmd_with_length(cmd, GOOD, 8 + lun_count * 8);
return 0;
}
EXPORT_SYMBOL(spc_emulate_report_luns);