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