You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
5.9 KiB
174 lines
5.9 KiB
From 709410b1d7f3d0b2b4e342cc46de2b45453d6c5c Mon Sep 17 00:00:00 2001 |
|
From: Ronnie Sahlberg <ronniesahlberg@gmail.com> |
|
Date: Sat, 18 May 2013 13:56:02 -0700 |
|
Subject: [RHEL7 libiscsi PATCH 15/18] TESTS: Add some REPORT SUPPORTED OPCODES tests |
|
|
|
Add a simple test that it works or is not implemented. |
|
|
|
Add a RCTD test to verify that with this flag clear we get command descriptors without CTDP set and with it set we get command descriptors with CTDP set and a timeout descriptor |
|
|
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
|
(cherry-picked from upstream commit 709410b1d7f3d0b2b4e342cc46de2b45453d6c5c) |
|
|
|
Fixes these errors in ARM compilation: |
|
|
|
lib/scsi-lowlevel.c: In function 'scsi_maintenancein_datain_unmarshall': |
|
lib/scsi-lowlevel.c:862:12: error: cast increases required alignment of target type [-Werror=cast-align] |
|
datain = (struct scsi_command_descriptor *)&task->datain.data[4]; |
|
^ |
|
lib/scsi-lowlevel.c:876:11: error: cast increases required alignment of target type [-Werror=cast-align] |
|
desc = (struct scsi_command_descriptor *)((char *)desc + desc_size); |
|
^ |
|
lib/scsi-lowlevel.c:877:13: error: cast increases required alignment of target type [-Werror=cast-align] |
|
datain = (struct scsi_command_descriptor *)((char *)datain + desc_size); |
|
^ |
|
--- |
|
include/scsi-lowlevel.h | 60 +++++++------- |
|
lib/scsi-lowlevel.c | 77 +++++++++--------- |
|
|
|
diff --git a/include/scsi-lowlevel.h b/include/scsi-lowlevel.h |
|
index 5693129..acdc936 100644 |
|
--- a/include/scsi-lowlevel.h |
|
+++ b/include/scsi-lowlevel.h |
|
@@ -739,24 +739,24 @@ struct scsi_get_lba_status { |
|
|
|
struct scsi_op_timeout_descriptor { |
|
uint16_t descriptor_length; |
|
- uint8_t reserved; |
|
uint8_t command_specific; |
|
uint32_t nominal_processing_timeout; |
|
uint32_t recommended_timeout; |
|
|
|
}; |
|
struct scsi_command_descriptor { |
|
- uint8_t op_code; |
|
- uint8_t reserved1; |
|
- uint16_t service_action; |
|
- uint8_t reserved2; |
|
- uint8_t reserved3; |
|
- uint16_t cdb_length; |
|
- struct scsi_op_timeout_descriptor to[0]; |
|
+ uint8_t opcode; |
|
+ uint16_t sa; |
|
+ uint8_t ctdp; |
|
+ uint8_t servactv; |
|
+ uint16_t cdb_len; |
|
+ |
|
+ /* only present if CTDP==1 */ |
|
+ struct scsi_op_timeout_descriptor to; |
|
}; |
|
|
|
struct scsi_report_supported_op_codes { |
|
- uint32_t num_descriptors; |
|
+ int num_descriptors; |
|
struct scsi_command_descriptor descriptors[0]; |
|
}; |
|
|
|
diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c |
|
index 3c02ace..c091539 100644 |
|
--- a/lib/scsi-lowlevel.c |
|
+++ b/lib/scsi-lowlevel.c |
|
@@ -806,12 +806,6 @@ scsi_persistentreservein_datain_unmarshall(struct scsi_task *task) |
|
} |
|
} |
|
|
|
-static inline int |
|
-scsi_maintenancein_return_timeouts(const struct scsi_task *task) |
|
-{ |
|
- return task->cdb[2] & 0x80; |
|
-} |
|
- |
|
static inline uint8_t |
|
scsi_maintenancein_sa(const struct scsi_task *task) |
|
{ |
|
@@ -841,9 +835,7 @@ static void * |
|
scsi_maintenancein_datain_unmarshall(struct scsi_task *task) |
|
{ |
|
struct scsi_report_supported_op_codes *rsoc; |
|
- struct scsi_command_descriptor *desc, *datain; |
|
- uint32_t len, i; |
|
- int return_timeouts, desc_size; |
|
+ int len, i; |
|
|
|
switch (scsi_maintenancein_sa(task)) { |
|
case SCSI_REPORT_SUPPORTED_OP_CODES: |
|
@@ -852,37 +844,52 @@ scsi_maintenancein_datain_unmarshall(struct scsi_task *task) |
|
} |
|
|
|
len = task_get_uint32(task, 0); |
|
- rsoc = scsi_malloc(task, sizeof(struct scsi_report_supported_op_codes) + len); |
|
+ /* len / 8 is not always correct since if CTDP==1 then the |
|
+ * descriptor is 20 bytes in size intead of 8. |
|
+ * It doesnt matter here though since it just means we would |
|
+ * allocate more descriptors at the end of the structure than |
|
+ * we strictly need. This avoids having to traverse the |
|
+ * datain buffer twice. |
|
+ */ |
|
+ rsoc = scsi_malloc(task, |
|
+ offsetof(struct scsi_report_supported_op_codes, |
|
+ descriptors) + |
|
+ len / 8 * sizeof(struct scsi_command_descriptor)); |
|
if (rsoc == NULL) { |
|
return NULL; |
|
} |
|
- /* Does the descriptor include command timeout info? */ |
|
- return_timeouts = scsi_maintenancein_return_timeouts(task); |
|
|
|
- /* Size of descriptor depends on whether timeout included. */ |
|
- desc_size = sizeof (struct scsi_command_descriptor); |
|
- if (return_timeouts) { |
|
- desc_size += sizeof (struct scsi_op_timeout_descriptor); |
|
- } |
|
- rsoc->num_descriptors = len / desc_size; |
|
- |
|
- desc = &rsoc->descriptors[0]; |
|
- datain = (struct scsi_command_descriptor *)&task->datain.data[4]; |
|
- |
|
- for (i=0; i < rsoc->num_descriptors; i++) { |
|
- desc->op_code = datain->op_code; |
|
- desc->service_action = ntohs(datain->service_action); |
|
- desc->cdb_length = ntohs(datain->cdb_length); |
|
- if (return_timeouts) { |
|
- desc->to[0].descriptor_length = ntohs(datain->to[0].descriptor_length); |
|
- desc->to[0].command_specific = datain->to[0].command_specific; |
|
- desc->to[0].nominal_processing_timeout |
|
- = ntohl(datain->to[0].nominal_processing_timeout); |
|
- desc->to[0].recommended_timeout |
|
- = ntohl(datain->to[0].recommended_timeout); |
|
+ rsoc->num_descriptors = 0; |
|
+ i = 4; |
|
+ while (len >= 8) { |
|
+ struct scsi_command_descriptor *desc; |
|
+ |
|
+ desc = &rsoc->descriptors[rsoc->num_descriptors++]; |
|
+ desc->opcode = task_get_uint8(task, i); |
|
+ desc->sa = task_get_uint16(task, i + 2); |
|
+ desc->ctdp = !!(task_get_uint8(task, i + 5) & 0x02); |
|
+ desc->servactv = !!(task_get_uint8(task, i + 5) & 0x01); |
|
+ desc->cdb_len = task_get_uint16(task, i + 6); |
|
+ |
|
+ len -= 8; |
|
+ i += 8; |
|
+ |
|
+ /* No tiemout description */ |
|
+ if (!desc->ctdp) { |
|
+ continue; |
|
} |
|
- desc = (struct scsi_command_descriptor *)((char *)desc + desc_size); |
|
- datain = (struct scsi_command_descriptor *)((char *)datain + desc_size); |
|
+ |
|
+ desc->to.descriptor_length = |
|
+ task_get_uint16(task, i); |
|
+ desc->to.command_specific = |
|
+ task_get_uint8(task, i + 3); |
|
+ desc->to.nominal_processing_timeout = |
|
+ task_get_uint32(task, i + 4); |
|
+ desc->to.recommended_timeout = |
|
+ task_get_uint32(task, i + 8); |
|
+ |
|
+ len -= desc->to.descriptor_length + 2; |
|
+ i += desc->to.descriptor_length + 2; |
|
} |
|
|
|
return rsoc; |
|
|
|
|