target: support zero allocation length in REQUEST SENSE
Similar to INQUIRY and MODE SENSE, construct the sense data in a buffer and later copy it to the scatterlist. Do not do anything, but still clear a pending unit attention condition, if the allocation length is zero. However, SPC tells us that "If a REQUEST SENSE command is terminated with CHECK CONDITION status [and] the REQUEST SENSE command was received on an I_T nexus with a pending unit attention condition (i.e., before the device server reports CHECK CONDITION status), then the device server shall not clear the pending unit attention condition." Do the transport_kmap_data_sg early to detect this case. It also tells us "Device servers shall not adjust the additional sense length to reflect truncation if the allocation length is less than the sense data available", so do not do that! Note that the err variable is write-only. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
parent
3717ef0c63
commit
32a8811ff1
2 changed files with 19 additions and 17 deletions
|
@ -877,9 +877,11 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
|
|||
static int spc_emulate_request_sense(struct se_cmd *cmd)
|
||||
{
|
||||
unsigned char *cdb = cmd->t_task_cdb;
|
||||
unsigned char *buf;
|
||||
unsigned char *rbuf;
|
||||
u8 ua_asc = 0, ua_ascq = 0;
|
||||
int err = 0;
|
||||
unsigned char buf[SE_SENSE_BUF];
|
||||
|
||||
memset(buf, 0, SE_SENSE_BUF);
|
||||
|
||||
if (cdb[1] & 0x01) {
|
||||
pr_err("REQUEST_SENSE description emulation not"
|
||||
|
@ -888,20 +890,21 @@ static int spc_emulate_request_sense(struct se_cmd *cmd)
|
|||
return -ENOSYS;
|
||||
}
|
||||
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
|
||||
if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
|
||||
rbuf = transport_kmap_data_sg(cmd);
|
||||
if (cmd->scsi_sense_reason != 0) {
|
||||
/*
|
||||
* Out of memory. We will fail with CHECK CONDITION, so
|
||||
* we must not clear the unit attention condition.
|
||||
*/
|
||||
target_complete_cmd(cmd, CHECK_CONDITION);
|
||||
return 0;
|
||||
} else if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
|
||||
/*
|
||||
* CURRENT ERROR, UNIT ATTENTION
|
||||
*/
|
||||
buf[0] = 0x70;
|
||||
buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
|
||||
|
||||
if (cmd->data_length < 18) {
|
||||
buf[7] = 0x00;
|
||||
err = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
/*
|
||||
* The Additional Sense Code (ASC) from the UNIT ATTENTION
|
||||
*/
|
||||
|
@ -915,11 +918,6 @@ static int spc_emulate_request_sense(struct se_cmd *cmd)
|
|||
buf[0] = 0x70;
|
||||
buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE;
|
||||
|
||||
if (cmd->data_length < 18) {
|
||||
buf[7] = 0x00;
|
||||
err = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
/*
|
||||
* NO ADDITIONAL SENSE INFORMATION
|
||||
*/
|
||||
|
@ -927,8 +925,11 @@ static int spc_emulate_request_sense(struct se_cmd *cmd)
|
|||
buf[7] = 0x0A;
|
||||
}
|
||||
|
||||
end:
|
||||
transport_kunmap_data_sg(cmd);
|
||||
if (rbuf) {
|
||||
memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
|
||||
transport_kunmap_data_sg(cmd);
|
||||
}
|
||||
|
||||
target_complete_cmd(cmd, GOOD);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -121,6 +121,7 @@
|
|||
|
||||
#define SE_INQUIRY_BUF 512
|
||||
#define SE_MODE_PAGE_BUF 512
|
||||
#define SE_SENSE_BUF 96
|
||||
|
||||
/* struct se_hba->hba_flags */
|
||||
enum hba_flags_table {
|
||||
|
|
Loading…
Reference in a new issue