Add support and tests for ExtendedCopy and ReceiveCopyResults
From sushma.gurram@sandisk.com Add support to libiscsi and tests for these two opcodes. Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
This commit is contained in:
@@ -54,6 +54,8 @@ enum scsi_opcode {
|
||||
SCSI_OPCODE_MODESENSE10 = 0x5A,
|
||||
SCSI_OPCODE_PERSISTENT_RESERVE_IN = 0x5E,
|
||||
SCSI_OPCODE_PERSISTENT_RESERVE_OUT = 0x5F,
|
||||
SCSI_OPCODE_EXTENDED_COPY = 0x83,
|
||||
SCSI_OPCODE_RECEIVE_COPY_RESULTS = 0x84,
|
||||
SCSI_OPCODE_READ16 = 0x88,
|
||||
SCSI_OPCODE_COMPARE_AND_WRITE = 0x89,
|
||||
SCSI_OPCODE_WRITE16 = 0x8A,
|
||||
@@ -148,7 +150,10 @@ enum scsi_sense_key {
|
||||
EXTERN const char *scsi_sense_key_str(int key);
|
||||
|
||||
/* ascq */
|
||||
#define SCSI_SENSE_ASCQ_NO_ADDL_SENSE 0x0000
|
||||
#define SCSI_SENSE_ASCQ_SANITIZE_IN_PROGRESS 0x041b
|
||||
#define SCSI_SENSE_ASCQ_UNREACHABLE_COPY_TARGET 0x0804
|
||||
#define SCSI_SENSE_ASCQ_COPY_TARGET_DEVICE_NOT_REACHABLE 0x0d02
|
||||
#define SCSI_SENSE_ASCQ_WRITE_AFTER_SANITIZE_REQUIRED 0x1115
|
||||
#define SCSI_SENSE_ASCQ_PARAMETER_LIST_LENGTH_ERROR 0x1a00
|
||||
#define SCSI_SENSE_ASCQ_MISCOMPARE_DURING_VERIFY 0x1d00
|
||||
@@ -158,6 +163,10 @@ EXTERN const char *scsi_sense_key_str(int key);
|
||||
#define SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB 0x2400
|
||||
#define SCSI_SENSE_ASCQ_LOGICAL_UNIT_NOT_SUPPORTED 0x2500
|
||||
#define SCSI_SENSE_ASCQ_INVALID_FIELD_IN_PARAMETER_LIST 0x2600
|
||||
#define SCSI_SENSE_ASCQ_TOO_MANY_TARGET_DESCRIPTORS 0x2606
|
||||
#define SCSI_SENSE_ASCQ_UNSUPPORTED_TARGET_DESCRIPTOR_TYPE_CODE 0x2607
|
||||
#define SCSI_SENSE_ASCQ_TOO_MANY_SEGMENT_DESCRIPTORS 0x2608
|
||||
#define SCSI_SENSE_ASCQ_UNSUPPORTED_SEGMENT_DESCRIPTOR_TYPE_CODE 0x2609
|
||||
#define SCSI_SENSE_ASCQ_WRITE_PROTECTED 0x2700
|
||||
#define SCSI_SENSE_ASCQ_HARDWARE_WRITE_PROTECTED 0x2701
|
||||
#define SCSI_SENSE_ASCQ_SOFTWARE_WRITE_PROTECTED 0x2702
|
||||
@@ -348,7 +357,6 @@ EXTERN struct scsi_task *scsi_cdb_testunitready(void);
|
||||
EXTERN struct scsi_task *scsi_cdb_sanitize(int immed, int ause, int sa,
|
||||
int param_len);
|
||||
|
||||
|
||||
/*
|
||||
* REPORTLUNS
|
||||
*/
|
||||
@@ -1095,6 +1103,78 @@ EXTERN struct scsi_task *scsi_cdb_writeverify12(uint32_t lba, uint32_t xferlen,
|
||||
EXTERN struct scsi_task *scsi_cdb_writeverify16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int bytchk, int group_number);
|
||||
|
||||
|
||||
/*
|
||||
* EXTENDED COPY
|
||||
*/
|
||||
#define XCOPY_DESC_OFFSET 16
|
||||
#define SEG_DESC_SRC_INDEX_OFFSET 4
|
||||
enum list_id_usage {
|
||||
LIST_ID_USAGE_HOLD = 0,
|
||||
LIST_ID_USAGE_DISCARD = 2,
|
||||
LIST_ID_USAGE_DISABLE = 3
|
||||
};
|
||||
|
||||
enum ec_descr_type_code {
|
||||
/* Segment descriptors : 0x00 to 0xBF */
|
||||
BLK_TO_STRM_SEG_DESCR = 0x00,
|
||||
STRM_TO_BLK_SEG_DESCR = 0x01,
|
||||
BLK_TO_BLK_SEG_DESCR = 0x02,
|
||||
STRM_TO_STRM_SEG_DESCR = 0x03,
|
||||
|
||||
/* Target descriptors : 0xEO to 0xFE */
|
||||
IDENT_DESCR_TGT_DESCR = 0xE4,
|
||||
IPV4_TGT_DESCR = 0xE5,
|
||||
IPV6_TGT_DESCR = 0xEA,
|
||||
IP_COPY_SVC_TGT_DESCR = 0xEB
|
||||
};
|
||||
|
||||
enum lu_id_type {
|
||||
LU_ID_TYPE_LUN = 0x00,
|
||||
LU_ID_TYPE_PROXY_TOKEN = 0x01,
|
||||
LU_ID_TYPE_RSVD = 0x02,
|
||||
LU_ID_TYPE_RSVD1 = 0x03
|
||||
};
|
||||
|
||||
EXTERN struct scsi_task *scsi_cdb_extended_copy(int immed);
|
||||
|
||||
/*
|
||||
* RECEIVE COPY RESULTS
|
||||
*/
|
||||
enum scsi_copy_results_sa {
|
||||
SCSI_COPY_RESULTS_COPY_STATUS = 0,
|
||||
SCSI_COPY_RESULTS_RECEIVE_DATA = 1,
|
||||
SCSI_COPY_RESULTS_OP_PARAMS = 3,
|
||||
SCSI_COPY_RESULTS_FAILED_SEGMENT = 4,
|
||||
};
|
||||
|
||||
EXTERN struct scsi_task *scsi_cdb_receive_copy_results(enum scsi_copy_results_sa sa, int list_id, int xferlen);
|
||||
|
||||
struct scsi_copy_results_copy_status {
|
||||
uint32_t available_data;
|
||||
uint8_t copy_manager_status;
|
||||
uint8_t hdd;
|
||||
uint16_t segments_processed;
|
||||
uint8_t transfer_count_units;
|
||||
uint32_t transfer_count;
|
||||
};
|
||||
|
||||
struct scsi_copy_results_op_params {
|
||||
uint32_t available_data;
|
||||
uint16_t max_target_desc_count;
|
||||
uint16_t max_segment_desc_count;
|
||||
uint32_t max_desc_list_length;
|
||||
uint32_t max_segment_length;
|
||||
uint32_t max_inline_data_length;
|
||||
uint32_t held_data_limit;
|
||||
uint32_t max_stream_device_transfer_size;
|
||||
uint16_t total_concurrent_copies;
|
||||
uint8_t max_concurrent_copies;
|
||||
uint8_t data_segment_granularity;
|
||||
uint8_t inline_data_granularity;
|
||||
uint8_t held_data_granularity;
|
||||
uint8_t impl_desc_list_length;
|
||||
uint8_t imp_desc_type_codes[0];
|
||||
};
|
||||
void *scsi_malloc(struct scsi_task *task, size_t size);
|
||||
|
||||
uint64_t scsi_get_uint64(const unsigned char *c);
|
||||
|
||||
@@ -159,6 +159,7 @@ iscsi_writesame16_sync
|
||||
iscsi_writesame16_task
|
||||
scsi_association_to_str
|
||||
scsi_cdb_compareandwrite
|
||||
scsi_cdb_extended_copy
|
||||
scsi_cdb_inquiry
|
||||
scsi_cdb_get_lba_status
|
||||
scsi_cdb_modeselect6
|
||||
@@ -177,6 +178,7 @@ scsi_cdb_read6
|
||||
scsi_cdb_readcapacity10
|
||||
scsi_cdb_readcapacity16
|
||||
scsi_cdb_readtoc
|
||||
scsi_cdb_receive_copy_results
|
||||
scsi_cdb_reserve6
|
||||
scsi_cdb_release6
|
||||
scsi_cdb_report_supported_opcodes
|
||||
|
||||
@@ -157,6 +157,7 @@ iscsi_writesame16_sync
|
||||
iscsi_writesame16_task
|
||||
scsi_association_to_str
|
||||
scsi_cdb_compareandwrite
|
||||
scsi_cdb_extended_copy
|
||||
scsi_cdb_inquiry
|
||||
scsi_cdb_get_lba_status
|
||||
scsi_cdb_modeselect6
|
||||
@@ -175,6 +176,7 @@ scsi_cdb_read6
|
||||
scsi_cdb_readcapacity10
|
||||
scsi_cdb_readcapacity16
|
||||
scsi_cdb_readtoc
|
||||
scsi_cdb_receive_copy_results
|
||||
scsi_cdb_reserve6
|
||||
scsi_cdb_release6
|
||||
scsi_cdb_report_supported_opcodes
|
||||
|
||||
@@ -834,6 +834,61 @@ scsi_persistentreservein_datain_getfullsize(struct scsi_task *task)
|
||||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
scsi_receivecopyresults_datain_unmarshall(struct scsi_task *task)
|
||||
{
|
||||
int sa = task->cdb[1] & 0x1f;
|
||||
int len, i;
|
||||
struct scsi_copy_results_copy_status *cs;
|
||||
struct scsi_copy_results_op_params *op;
|
||||
|
||||
switch (sa) {
|
||||
case SCSI_COPY_RESULTS_COPY_STATUS:
|
||||
len = task_get_uint32(task, 0);
|
||||
|
||||
cs = scsi_malloc(task, len+4);
|
||||
if (cs == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
cs->available_data = len;
|
||||
cs->copy_manager_status = task_get_uint8(task, 4) & 0x7F;
|
||||
cs->hdd = (task_get_uint8(task, 4) & 0x80) >> 7;
|
||||
cs->segments_processed = task_get_uint16(task, 5);
|
||||
cs->transfer_count_units = task_get_uint8(task, 7);
|
||||
cs->transfer_count = task_get_uint32(task, 8);
|
||||
return cs;
|
||||
|
||||
case SCSI_COPY_RESULTS_OP_PARAMS:
|
||||
len = task_get_uint32(task, 0);
|
||||
|
||||
op = scsi_malloc(task, len+4);
|
||||
if (op == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
op->available_data = len;
|
||||
op->max_target_desc_count = task_get_uint16(task, 8);
|
||||
op->max_segment_desc_count = task_get_uint16(task, 10);
|
||||
op->max_desc_list_length = task_get_uint32(task, 12);
|
||||
op->max_segment_length = task_get_uint32(task, 16);
|
||||
op->max_inline_data_length = task_get_uint32(task, 20);
|
||||
op->held_data_limit = task_get_uint32(task, 24);
|
||||
op->max_stream_device_transfer_size = task_get_uint32(task, 28);
|
||||
op->total_concurrent_copies = task_get_uint16(task, 34);
|
||||
op->max_concurrent_copies = task_get_uint8(task, 36);
|
||||
op->data_segment_granularity = task_get_uint8(task, 37);
|
||||
op->inline_data_granularity = task_get_uint8(task, 38);
|
||||
op->held_data_granularity = task_get_uint8(task, 39);
|
||||
op->impl_desc_list_length = task_get_uint8(task, 43);
|
||||
for (i = 0; i < (int)op->impl_desc_list_length; i++) {
|
||||
op->imp_desc_type_codes[i] = task_get_uint8(task, 44+i);
|
||||
}
|
||||
return op;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
scsi_persistentreservein_datain_unmarshall(struct scsi_task *task)
|
||||
{
|
||||
@@ -3230,6 +3285,63 @@ scsi_cdb_writeverify16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprot
|
||||
return task;
|
||||
}
|
||||
|
||||
/*
|
||||
* EXTENDED COPY
|
||||
*/
|
||||
struct scsi_task *
|
||||
scsi_cdb_extended_copy(int param_len)
|
||||
{
|
||||
struct scsi_task *task;
|
||||
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
if (task == NULL)
|
||||
return NULL;
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_EXTENDED_COPY;
|
||||
task->cdb[10] = (param_len >> 24) & 0xFF;
|
||||
task->cdb[11] = (param_len >> 16) & 0xFF;
|
||||
task->cdb[12] = (param_len >> 8) & 0xFF;
|
||||
task->cdb[13] = param_len & 0xFF;
|
||||
/* Inititalize other fields in CDB */
|
||||
task->cdb_size = 16;
|
||||
task->xfer_dir = SCSI_XFER_WRITE;
|
||||
task->expxferlen = param_len;
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
/*
|
||||
* RECEIVE COPY RESULTS
|
||||
*/
|
||||
struct scsi_task *
|
||||
scsi_cdb_receive_copy_results(enum scsi_copy_results_sa sa, int list_id, int xferlen)
|
||||
{
|
||||
struct scsi_task *task;
|
||||
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
if (task == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_RECEIVE_COPY_RESULTS;
|
||||
task->cdb[1] |= sa & 0x1f;
|
||||
task->cdb[2] = list_id & 0xFF;
|
||||
|
||||
scsi_set_uint32(&task->cdb[10], xferlen);
|
||||
|
||||
task->cdb_size = 16;
|
||||
if (xferlen != 0) {
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
} else {
|
||||
task->xfer_dir = SCSI_XFER_NONE;
|
||||
}
|
||||
task->expxferlen = xferlen;
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
int
|
||||
scsi_datain_getfullsize(struct scsi_task *task)
|
||||
{
|
||||
@@ -3281,6 +3393,8 @@ scsi_datain_unmarshall(struct scsi_task *task)
|
||||
return scsi_persistentreservein_datain_unmarshall(task);
|
||||
case SCSI_OPCODE_MAINTENANCE_IN:
|
||||
return scsi_maintenancein_datain_unmarshall(task);
|
||||
case SCSI_OPCODE_RECEIVE_COPY_RESULTS:
|
||||
return scsi_receivecopyresults_datain_unmarshall(task);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,12 @@ iscsi_test_cu_SOURCES = iscsi-test-cu.c \
|
||||
test_compareandwrite_simple.c \
|
||||
test_compareandwrite_dpofua.c \
|
||||
test_compareandwrite_miscompare.c \
|
||||
test_extendedcopy_simple.c \
|
||||
test_extendedcopy_param.c \
|
||||
test_extendedcopy_descr_limits.c \
|
||||
test_extendedcopy_descr_type.c \
|
||||
test_extendedcopy_validate_tgt_descr.c \
|
||||
test_extendedcopy_validate_seg_descr.c \
|
||||
test_get_lba_status_simple.c \
|
||||
test_get_lba_status_beyond_eol.c \
|
||||
test_get_lba_status_unmap_single.c \
|
||||
@@ -93,6 +99,8 @@ iscsi_test_cu_SOURCES = iscsi-test-cu.c \
|
||||
test_readcapacity16_protection.c \
|
||||
test_readcapacity16_simple.c \
|
||||
test_readonly_sbc.c \
|
||||
test_receive_copy_results_copy_status.c \
|
||||
test_receive_copy_results_op_params.c \
|
||||
test_report_supported_opcodes_one_command.c \
|
||||
test_report_supported_opcodes_rctd.c \
|
||||
test_report_supported_opcodes_servactv.c \
|
||||
|
||||
@@ -63,8 +63,12 @@ int no_medium_ascqs[3] = {
|
||||
int lba_oob_ascqs[1] = {
|
||||
SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE
|
||||
};
|
||||
int invalid_cdb_ascqs[1] = {
|
||||
SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB
|
||||
int invalid_cdb_ascqs[2] = {
|
||||
SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB,
|
||||
SCSI_SENSE_ASCQ_INVALID_FIELD_IN_PARAMETER_LIST
|
||||
};
|
||||
int param_list_len_err_ascqs[1] = {
|
||||
SCSI_SENSE_ASCQ_PARAMETER_LIST_LENGTH_ERROR
|
||||
};
|
||||
int write_protect_ascqs[3] = {
|
||||
SCSI_SENSE_ASCQ_WRITE_PROTECTED,
|
||||
@@ -80,6 +84,19 @@ int removal_ascqs[1] = {
|
||||
int miscompare_ascqs[1] = {
|
||||
SCSI_SENSE_ASCQ_MISCOMPARE_DURING_VERIFY
|
||||
};
|
||||
int too_many_desc_ascqs[2] = {
|
||||
SCSI_SENSE_ASCQ_TOO_MANY_TARGET_DESCRIPTORS,
|
||||
SCSI_SENSE_ASCQ_TOO_MANY_SEGMENT_DESCRIPTORS,
|
||||
};
|
||||
int unsupp_desc_code_ascqs[2] = {
|
||||
SCSI_SENSE_ASCQ_UNSUPPORTED_TARGET_DESCRIPTOR_TYPE_CODE,
|
||||
SCSI_SENSE_ASCQ_UNSUPPORTED_SEGMENT_DESCRIPTOR_TYPE_CODE
|
||||
};
|
||||
int copy_aborted_ascqs[3] = {
|
||||
SCSI_SENSE_ASCQ_NO_ADDL_SENSE,
|
||||
SCSI_SENSE_ASCQ_UNREACHABLE_COPY_TARGET,
|
||||
SCSI_SENSE_ASCQ_COPY_TARGET_DEVICE_NOT_REACHABLE
|
||||
};
|
||||
|
||||
struct scsi_inquiry_standard *inq;
|
||||
struct scsi_inquiry_logical_block_provisioning *inq_lbp;
|
||||
@@ -2528,3 +2545,217 @@ finished:
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Extended Copy */
|
||||
int extendedcopy(struct scsi_device *sdev, struct iscsi_data *data, int status, enum scsi_sense_key key, int *ascq, int num_ascq)
|
||||
{
|
||||
struct scsi_task *task;
|
||||
int ret;
|
||||
|
||||
logging(LOG_VERBOSE, "Send EXTENDED COPY (Expecting %s)",
|
||||
scsi_status_str(status));
|
||||
|
||||
if (!data_loss) {
|
||||
logging(LOG_NORMAL, "--dataloss flag is not set in. Skipping extendedcopy\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
task = scsi_cdb_extended_copy(data->size);
|
||||
|
||||
assert(task != NULL);
|
||||
|
||||
send_scsi_command(sdev, task, data);
|
||||
|
||||
ret = check_result("EXTENDEDCOPY", sdev, task, status, key, ascq, num_ascq);
|
||||
scsi_free_scsi_task(task);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int get_desc_len(enum ec_descr_type_code desc_type)
|
||||
{
|
||||
int desc_len = 0;
|
||||
switch (desc_type) {
|
||||
/* Segment Descriptors */
|
||||
case BLK_TO_STRM_SEG_DESCR:
|
||||
case STRM_TO_BLK_SEG_DESCR:
|
||||
desc_len = 0x18;
|
||||
break;
|
||||
case BLK_TO_BLK_SEG_DESCR:
|
||||
desc_len = 0x1C;
|
||||
break;
|
||||
case STRM_TO_STRM_SEG_DESCR:
|
||||
desc_len = 0x14;
|
||||
break;
|
||||
|
||||
/* Target Descriptors */
|
||||
case IPV6_TGT_DESCR:
|
||||
case IP_COPY_SVC_TGT_DESCR:
|
||||
desc_len = 64;
|
||||
break;
|
||||
case IDENT_DESCR_TGT_DESCR:
|
||||
default:
|
||||
if (desc_type >= 0xE0 && desc_type <= 0xE9)
|
||||
desc_len = 32;
|
||||
}
|
||||
|
||||
return desc_len;
|
||||
}
|
||||
|
||||
void populate_ident_tgt_desc(unsigned char *buf, struct scsi_device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct scsi_task *inq_di_task = NULL;
|
||||
struct scsi_inquiry_device_identification *inq_di = NULL;
|
||||
struct scsi_inquiry_device_designator *desig, *tgt_desig = NULL;
|
||||
enum scsi_designator_type prev_type = 0;
|
||||
|
||||
ret = inquiry(dev, &inq_di_task, 1, SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION, 255, EXPECT_STATUS_GOOD);
|
||||
if (ret < 0 || inq_di_task == NULL) {
|
||||
logging(LOG_NORMAL, "Failed to read Device Identification page");
|
||||
goto finished;
|
||||
} else {
|
||||
inq_di = scsi_datain_unmarshall(inq_di_task);
|
||||
if (inq_di == NULL) {
|
||||
logging(LOG_NORMAL, "Failed to unmarshall inquiry datain blob");
|
||||
goto finished;
|
||||
}
|
||||
}
|
||||
|
||||
for (desig = inq_di->designators; desig; desig = desig->next) {
|
||||
switch (desig->designator_type) {
|
||||
case SCSI_DESIGNATOR_TYPE_VENDOR_SPECIFIC:
|
||||
case SCSI_DESIGNATOR_TYPE_T10_VENDORT_ID:
|
||||
case SCSI_DESIGNATOR_TYPE_EUI_64:
|
||||
case SCSI_DESIGNATOR_TYPE_NAA:
|
||||
if (prev_type <= desig->designator_type) {
|
||||
tgt_desig = desig;
|
||||
prev_type = desig->designator_type;
|
||||
}
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (tgt_desig == NULL) {
|
||||
logging(LOG_NORMAL, "No suitalble target descriptor format found");
|
||||
goto finished;
|
||||
}
|
||||
|
||||
buf[0] = tgt_desig->code_set;
|
||||
buf[1] = (tgt_desig->designator_type & 0xF) | ((tgt_desig->association & 3) << 4);
|
||||
buf[3] = tgt_desig->designator_length;
|
||||
memcpy(buf + 4, tgt_desig->designator, tgt_desig->designator_length);
|
||||
|
||||
finished:
|
||||
scsi_free_scsi_task(inq_di_task);
|
||||
}
|
||||
|
||||
int populate_tgt_desc(unsigned char *desc, enum ec_descr_type_code desc_type, int luid_type, int nul, int peripheral_type, int rel_init_port_id, int pad, struct scsi_device *dev)
|
||||
{
|
||||
desc[0] = desc_type;
|
||||
desc[1] = (luid_type << 6) | (nul << 5) | peripheral_type;
|
||||
desc[2] = (rel_init_port_id >> 8) & 0xFF;
|
||||
desc[3] = rel_init_port_id & 0xFF;
|
||||
|
||||
if (desc_type == IDENT_DESCR_TGT_DESCR)
|
||||
populate_ident_tgt_desc(desc+4, dev);
|
||||
|
||||
if (peripheral_type == 0) {
|
||||
// Issue readcapacity for each sd if testing with different LUs
|
||||
// If single LU, use block_size from prior readcapacity involcation
|
||||
desc[28] = pad << 2;
|
||||
desc[29] = (block_size >> 16) & 0xFF;
|
||||
desc[30] = (block_size >> 8) & 0xFF;
|
||||
desc[31] = block_size & 0xFF;
|
||||
}
|
||||
return get_desc_len(desc_type);
|
||||
}
|
||||
|
||||
int populate_seg_desc_hdr(unsigned char *hdr, enum ec_descr_type_code desc_type, int dc, int cat, int src_index, int dst_index)
|
||||
{
|
||||
int desc_len = get_desc_len(desc_type);
|
||||
|
||||
hdr[0] = desc_type;
|
||||
hdr[1] = ((dc << 1) | cat) & 0xFF;
|
||||
hdr[2] = (desc_len >> 8) & 0xFF;
|
||||
hdr[3] = (desc_len - SEG_DESC_SRC_INDEX_OFFSET) & 0xFF; /* don't account for the first 4 bytes in descriptor header*/
|
||||
hdr[4] = (src_index >> 8) & 0xFF;
|
||||
hdr[5] = src_index & 0xFF;
|
||||
hdr[6] = (dst_index >> 8) & 0xFF;
|
||||
hdr[7] = dst_index & 0xFF;
|
||||
|
||||
return desc_len;
|
||||
}
|
||||
|
||||
int populate_seg_desc_b2b(unsigned char *desc, int dc, int cat, int src_index, int dst_index, int num_blks, uint64_t src_lba, uint64_t dst_lba)
|
||||
{
|
||||
int desc_len = populate_seg_desc_hdr(desc, BLK_TO_BLK_SEG_DESCR, dc, cat, src_index, dst_index);
|
||||
|
||||
desc[10] = (num_blks >> 8) & 0xFF;
|
||||
desc[11] = num_blks & 0xFF;
|
||||
desc[12] = (src_lba >> 56) & 0xFF;
|
||||
desc[13] = (src_lba >> 48) & 0xFF;
|
||||
desc[14] = (src_lba >> 40) & 0xFF;
|
||||
desc[15] = (src_lba >> 32) & 0xFF;
|
||||
desc[16] = (src_lba >> 24) & 0xFF;
|
||||
desc[17] = (src_lba >> 16) & 0xFF;
|
||||
desc[18] = (src_lba >> 8) & 0xFF;
|
||||
desc[19] = src_lba & 0xFF;
|
||||
desc[20] = (dst_lba >> 56) & 0xFF;
|
||||
desc[21] = (dst_lba >> 48) & 0xFF;
|
||||
desc[22] = (dst_lba >> 40) & 0xFF;
|
||||
desc[23] = (dst_lba >> 32) & 0xFF;
|
||||
desc[24] = (dst_lba >> 24) & 0xFF;
|
||||
desc[25] = (dst_lba >> 16) & 0xFF;
|
||||
desc[26] = (dst_lba >> 8) & 0xFF;
|
||||
desc[27] = dst_lba & 0xFF;
|
||||
|
||||
return desc_len;
|
||||
}
|
||||
|
||||
void populate_param_header(unsigned char *buf, int list_id, int str, int list_id_usage, int prio, int tgt_desc_len, int seg_desc_len, int inline_data_len)
|
||||
{
|
||||
buf[0] = list_id;
|
||||
buf[1] = ((str & 1) << 5) | ((list_id_usage & 3) << 3) | (prio & 7);
|
||||
buf[2] = (tgt_desc_len >> 8) & 0xFF;
|
||||
buf[3] = tgt_desc_len & 0xFF;
|
||||
buf[8] = (seg_desc_len >> 24) & 0xFF;
|
||||
buf[9] = (seg_desc_len >> 16) & 0xFF;
|
||||
buf[10] = (seg_desc_len >> 8) & 0xFF;
|
||||
buf[11] = seg_desc_len & 0xFF;
|
||||
buf[12] = (inline_data_len >> 24) & 0xFF;
|
||||
buf[13] = (inline_data_len >> 16) & 0xFF;
|
||||
buf[14] = (inline_data_len >> 8) & 0xFF;
|
||||
buf[15] = inline_data_len & 0xFF;
|
||||
}
|
||||
|
||||
int receive_copy_results(struct scsi_device *sdev, enum scsi_copy_results_sa sa, int list_id, void **datap, int status, enum scsi_sense_key key, int *ascq, int num_ascq)
|
||||
{
|
||||
int ret;
|
||||
struct scsi_task *task;
|
||||
|
||||
logging(LOG_VERBOSE, "Send RECEIVE COPY RESULTS");
|
||||
|
||||
task = scsi_cdb_receive_copy_results(sa, list_id, 1024);
|
||||
assert(task != NULL);
|
||||
|
||||
task = send_scsi_command(sdev, task, NULL);
|
||||
|
||||
ret = check_result("RECEIVECOPYRESULT", sdev, task, status, key, ascq, num_ascq);
|
||||
|
||||
if (task->status == SCSI_STATUS_GOOD && datap != NULL) {
|
||||
*datap = scsi_datain_unmarshall(task);
|
||||
if (*datap == NULL) {
|
||||
logging(LOG_NORMAL,
|
||||
"[FAIL] failed to unmarshall RECEIVE COPY RESULTS data. %s",
|
||||
iscsi_get_error(sdev->iscsi_ctx));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ret = check_result("RECEIVECOPYRESULT", sdev, task, status, key, ascq, num_ascq);
|
||||
if (task)
|
||||
scsi_free_scsi_task(task);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -37,20 +37,28 @@ extern const char *initiatorname2;
|
||||
#define EXPECT_STATUS_GOOD SCSI_STATUS_GOOD, SCSI_SENSE_NO_SENSE, NULL, 0
|
||||
#define EXPECT_NO_MEDIUM SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_NOT_READY, no_medium_ascqs, 3
|
||||
#define EXPECT_LBA_OOB SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_ILLEGAL_REQUEST, lba_oob_ascqs, 1
|
||||
#define EXPECT_INVALID_FIELD_IN_CDB SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_ILLEGAL_REQUEST, invalid_cdb_ascqs, 1
|
||||
#define EXPECT_INVALID_FIELD_IN_CDB SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_ILLEGAL_REQUEST, invalid_cdb_ascqs,2
|
||||
#define EXPECT_PARAM_LIST_LEN_ERR SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_ILLEGAL_REQUEST, param_list_len_err_ascqs, 1
|
||||
#define EXPECT_TOO_MANY_DESCR SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_ILLEGAL_REQUEST, too_many_desc_ascqs, 2
|
||||
#define EXPECT_UNSUPP_DESCR_CODE SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_ILLEGAL_REQUEST, unsupp_desc_code_ascqs, 2
|
||||
#define EXPECT_MISCOMPARE SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_MISCOMPARE, miscompare_ascqs, 1
|
||||
#define EXPECT_WRITE_PROTECTED SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_DATA_PROTECTION, write_protect_ascqs, 3
|
||||
#define EXPECT_SANITIZE SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_NOT_READY, sanitize_ascqs, 1
|
||||
#define EXPECT_REMOVAL_PREVENTED SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_ILLEGAL_REQUEST, removal_ascqs, 1
|
||||
#define EXPECT_RESERVATION_CONFLICT SCSI_STATUS_RESERVATION_CONFLICT, 0, NULL, 0
|
||||
#define EXPECT_COPY_ABORTED SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_COPY_ABORTED, copy_aborted_ascqs, 3
|
||||
|
||||
int no_medium_ascqs[3];
|
||||
int lba_oob_ascqs[1];
|
||||
int invalid_cdb_ascqs[1];
|
||||
int invalid_cdb_ascqs[2];
|
||||
int param_list_len_err_ascqs[1];
|
||||
int too_many_desc_ascqs[2];
|
||||
int unsupp_desc_code_ascqs[2];
|
||||
int write_protect_ascqs[3];
|
||||
int sanitize_ascqs[1];
|
||||
int removal_ascqs[1];
|
||||
int miscompare_ascqs[1];
|
||||
int copy_aborted_ascqs[3];
|
||||
|
||||
extern int loglevel;
|
||||
#define LOG_SILENT 0
|
||||
@@ -314,5 +322,11 @@ int writeverify16(struct scsi_device *sdev, uint64_t lba, uint32_t datalen, int
|
||||
int set_swp(struct scsi_device *sdev);
|
||||
int clear_swp(struct scsi_device *sdev);
|
||||
|
||||
|
||||
int extendedcopy(struct scsi_device *sdev, struct iscsi_data *data, int status, enum scsi_sense_key key, int *ascq, int num_ascq);
|
||||
int get_desc_len(enum ec_descr_type_code desc_type);
|
||||
int populate_tgt_desc(unsigned char *desc, enum ec_descr_type_code desc_type, int luid_type, int nul, int peripheral_type, int rel_init_port_id, int pad, struct scsi_device *dev);
|
||||
int populate_seg_desc_hdr(unsigned char *hdr, enum ec_descr_type_code desc_type, int dc, int cat, int src_index, int dst_index);
|
||||
int populate_seg_desc_b2b(unsigned char *desc, int dc, int cat, int src_index, int dst_index, int num_blks, uint64_t src_lba, uint64_t dst_lba);
|
||||
void populate_param_header(unsigned char *buf, int list_id, int str, int list_id_usage, int prio, int tgt_desc_len, int seg_desc_len, int inline_data_len);
|
||||
int receive_copy_results(struct scsi_device *sdev, enum scsi_copy_results_sa sa, int list_id, void **datap, int status, enum scsi_sense_key key, int *ascq, int num_ascq);
|
||||
#endif /* _ISCSI_SUPPORT_H_ */
|
||||
|
||||
@@ -262,6 +262,22 @@ static CU_TestInfo tests_sanitize[] = {
|
||||
CU_TEST_INFO_NULL
|
||||
};
|
||||
|
||||
static CU_TestInfo tests_extended_copy[] = {
|
||||
{ (char *)"Simple", test_extendedcopy_simple },
|
||||
{ (char *)"ParamHdr", test_extendedcopy_param },
|
||||
{ (char *)"DescrLimits", test_extendedcopy_descr_limits },
|
||||
{ (char *)"DescrType", test_extendedcopy_descr_type },
|
||||
{ (char *)"ValidTgtDescr", test_extendedcopy_validate_tgt_descr },
|
||||
{ (char *)"ValidSegDescr", test_extendedcopy_validate_seg_descr },
|
||||
CU_TEST_INFO_NULL
|
||||
};
|
||||
|
||||
static CU_TestInfo tests_receive_copy_results[] = {
|
||||
{ (char *)"CopyStatus", test_receive_copy_results_copy_status },
|
||||
{ (char *)"OpParams", test_receive_copy_results_op_params },
|
||||
CU_TEST_INFO_NULL
|
||||
};
|
||||
|
||||
static CU_TestInfo tests_report_supported_opcodes[] = {
|
||||
{ (char *)"Simple", test_report_supported_opcodes_simple },
|
||||
{ (char *)"OneCommand", test_report_supported_opcodes_one_command },
|
||||
@@ -436,6 +452,7 @@ typedef struct libiscsi_suite_info {
|
||||
/* SCSI protocol tests */
|
||||
static libiscsi_suite_info scsi_suites[] = {
|
||||
{ "CompareAndWrite", NON_PGR_FUNCS, tests_compareandwrite },
|
||||
{ "ExtendedCopy", NON_PGR_FUNCS, tests_extended_copy },
|
||||
{ "GetLBAStatus", NON_PGR_FUNCS, tests_get_lba_status },
|
||||
{ "Inquiry", NON_PGR_FUNCS, tests_inquiry },
|
||||
{ "Mandatory", NON_PGR_FUNCS, tests_mandatory },
|
||||
@@ -456,6 +473,7 @@ static libiscsi_suite_info scsi_suites[] = {
|
||||
{ "ReadCapacity10", NON_PGR_FUNCS, tests_readcapacity10 },
|
||||
{ "ReadCapacity16", NON_PGR_FUNCS, tests_readcapacity16 },
|
||||
{ "ReadOnly", NON_PGR_FUNCS, tests_readonly },
|
||||
{ "ReceiveCopyResults", NON_PGR_FUNCS, tests_receive_copy_results },
|
||||
{ "ReportSupportedOpcodes", NON_PGR_FUNCS,
|
||||
tests_report_supported_opcodes },
|
||||
{ "Reserve6", NON_PGR_FUNCS, tests_reserve6 },
|
||||
@@ -517,6 +535,7 @@ static libiscsi_suite_info iscsi_suites[] = {
|
||||
/* All tests */
|
||||
static libiscsi_suite_info all_suites[] = {
|
||||
{ "CompareAndWrite", NON_PGR_FUNCS, tests_compareandwrite },
|
||||
{ "ExtendedCopy", NON_PGR_FUNCS, tests_extended_copy },
|
||||
{ "GetLBAStatus", NON_PGR_FUNCS, tests_get_lba_status },
|
||||
{ "Inquiry", NON_PGR_FUNCS, tests_inquiry },
|
||||
{ "Mandatory", NON_PGR_FUNCS, tests_mandatory },
|
||||
@@ -538,6 +557,7 @@ static libiscsi_suite_info all_suites[] = {
|
||||
{ "ReadCapacity10", NON_PGR_FUNCS, tests_readcapacity10 },
|
||||
{ "ReadCapacity16", NON_PGR_FUNCS, tests_readcapacity16 },
|
||||
{ "ReadOnly", NON_PGR_FUNCS, tests_readonly },
|
||||
{ "ReceiveCopyResults", NON_PGR_FUNCS, tests_receive_copy_results },
|
||||
{ "ReportSupportedOpcodes", NON_PGR_FUNCS,
|
||||
tests_report_supported_opcodes },
|
||||
{ "Reserve6", NON_PGR_FUNCS, tests_reserve6 },
|
||||
|
||||
@@ -52,6 +52,13 @@ void test_compareandwrite_simple(void);
|
||||
void test_compareandwrite_dpofua(void);
|
||||
void test_compareandwrite_miscompare(void);
|
||||
|
||||
void test_extendedcopy_simple(void);
|
||||
void test_extendedcopy_param(void);
|
||||
void test_extendedcopy_descr_limits(void);
|
||||
void test_extendedcopy_descr_type(void);
|
||||
void test_extendedcopy_validate_tgt_descr(void);
|
||||
void test_extendedcopy_validate_seg_descr(void);
|
||||
|
||||
void test_get_lba_status_simple(void);
|
||||
void test_get_lba_status_beyond_eol(void);
|
||||
void test_get_lba_status_unmap_single(void);
|
||||
@@ -158,6 +165,9 @@ void test_readcapacity16_simple(void);
|
||||
|
||||
void test_readonly_sbc(void);
|
||||
|
||||
void test_receive_copy_results_copy_status(void);
|
||||
void test_receive_copy_results_op_params(void);
|
||||
|
||||
void test_report_supported_opcodes_one_command(void);
|
||||
void test_report_supported_opcodes_rctd(void);
|
||||
void test_report_supported_opcodes_servactv(void);
|
||||
|
||||
120
test-tool/test_extendedcopy_descr_limits.c
Normal file
120
test-tool/test_extendedcopy_descr_limits.c
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
Copyright (c) 2015 SanDisk Corp.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include "scsi-lowlevel.h"
|
||||
#include "iscsi-test-cu.h"
|
||||
|
||||
int init_xcopy_descr(unsigned char *buf, int offset, int num_tgt_desc,
|
||||
int num_seg_desc, int *tgt_desc_len, int *seg_desc_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Initialize target descriptor list with num_tgt_desc
|
||||
* target descriptor */
|
||||
for (i = 0; i < num_tgt_desc; i++)
|
||||
offset += populate_tgt_desc(buf+offset, IDENT_DESCR_TGT_DESCR,
|
||||
LU_ID_TYPE_LUN, 0, 0, 0, 0, sd);
|
||||
*tgt_desc_len = offset - XCOPY_DESC_OFFSET;
|
||||
|
||||
/* Iniitialize segment descriptor list with num_seg_desc
|
||||
* segment descriptor */
|
||||
for (i = 0; i < num_seg_desc; i++)
|
||||
offset += populate_seg_desc_b2b(buf+offset, 0, 0, 0, 0,
|
||||
2048, 0, num_blocks - 2048);
|
||||
*seg_desc_len = offset - XCOPY_DESC_OFFSET - *tgt_desc_len;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
void
|
||||
test_extendedcopy_descr_limits(void)
|
||||
{
|
||||
int ret;
|
||||
struct iscsi_data data;
|
||||
unsigned char *xcopybuf;
|
||||
struct scsi_copy_results_op_params *opp;
|
||||
int tgt_desc_len = 0, seg_desc_len = 0;
|
||||
unsigned int alloc_len;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test EXTENDED COPY descriptor limits");
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
|
||||
logging(LOG_VERBOSE, "Issue RECEIVE COPY RESULTS (OPERATING PARAMS)");
|
||||
ret = receive_copy_results(sd, SCSI_COPY_RESULTS_OP_PARAMS, 0,
|
||||
(void **)&opp, EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
/* Allocate buffer to accommodate (MAX+1) target and
|
||||
* segment descriptors */
|
||||
alloc_len = XCOPY_DESC_OFFSET +
|
||||
(opp->max_target_desc_count+1) *
|
||||
get_desc_len(IDENT_DESCR_TGT_DESCR) +
|
||||
(opp->max_segment_desc_count+1) *
|
||||
get_desc_len(BLK_TO_BLK_SEG_DESCR);
|
||||
data.data = alloca(alloc_len);
|
||||
xcopybuf = data.data;
|
||||
|
||||
logging(LOG_VERBOSE,
|
||||
"Test sending more than supported target descriptors");
|
||||
data.size = init_xcopy_descr(xcopybuf, XCOPY_DESC_OFFSET,
|
||||
(opp->max_target_desc_count+1), 1,
|
||||
&tgt_desc_len, &seg_desc_len);
|
||||
populate_param_header(xcopybuf, 1, 0, 0, 0,
|
||||
tgt_desc_len, seg_desc_len, 0);
|
||||
ret = extendedcopy(sd, &data, EXPECT_TOO_MANY_DESCR);
|
||||
if (ret == -2) {
|
||||
CU_PASS("[SKIPPED] Target does not support "
|
||||
"EXTENDED_COPY. Skipping test");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE,
|
||||
"Test sending more than supported segment descriptors");
|
||||
memset(xcopybuf, 0, alloc_len);
|
||||
data.size = init_xcopy_descr(xcopybuf, XCOPY_DESC_OFFSET, 1,
|
||||
(opp->max_segment_desc_count+1),
|
||||
&tgt_desc_len, &seg_desc_len);
|
||||
populate_param_header(xcopybuf, 2, 0, 0, 0,
|
||||
tgt_desc_len, seg_desc_len, 0);
|
||||
ret = extendedcopy(sd, &data, EXPECT_TOO_MANY_DESCR);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE,
|
||||
"Test sending descriptors > Maximum Descriptor List Length");
|
||||
memset(xcopybuf, 0, alloc_len);
|
||||
if (opp->max_desc_list_length < alloc_len) {
|
||||
data.size = init_xcopy_descr(xcopybuf, XCOPY_DESC_OFFSET,
|
||||
(opp->max_target_desc_count+1),
|
||||
(opp->max_segment_desc_count+1),
|
||||
&tgt_desc_len, &seg_desc_len);
|
||||
populate_param_header(xcopybuf, 3, 0, 0, 0,
|
||||
tgt_desc_len, seg_desc_len, 0);
|
||||
ret = extendedcopy(sd, &data, EXPECT_PARAM_LIST_LEN_ERR);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
}
|
||||
93
test-tool/test_extendedcopy_descr_type.c
Normal file
93
test-tool/test_extendedcopy_descr_type.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
Copyright (c) 2015 SanDisk Corp.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include "scsi-lowlevel.h"
|
||||
#include "iscsi-test-cu.h"
|
||||
|
||||
int init_xcopybuf(unsigned char *buf, int tgt_desc_type, int seg_desc_type,
|
||||
int *tgt_desc_len, int *seg_desc_len)
|
||||
{
|
||||
int offset = XCOPY_DESC_OFFSET;
|
||||
|
||||
offset += populate_tgt_desc(buf+offset, tgt_desc_type, LU_ID_TYPE_LUN,
|
||||
0, 0, 0, 0, sd);
|
||||
*tgt_desc_len = offset - XCOPY_DESC_OFFSET;
|
||||
if (seg_desc_type == BLK_TO_BLK_SEG_DESCR)
|
||||
offset += populate_seg_desc_b2b(buf+offset, 0, 0, 0, 0, 2048, 0,
|
||||
num_blocks - 2048);
|
||||
else
|
||||
offset += populate_seg_desc_hdr(buf+offset, seg_desc_type,
|
||||
0, 0, 0, 0);
|
||||
*seg_desc_len = offset - XCOPY_DESC_OFFSET - *tgt_desc_len;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
void
|
||||
test_extendedcopy_descr_type(void)
|
||||
{
|
||||
int ret;
|
||||
int tgt_desc_len = 0, seg_desc_len = 0, alloc_len;
|
||||
struct iscsi_data data;
|
||||
unsigned char *xcopybuf;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE,
|
||||
"Test EXTENDED COPY unsupported descriptor types");
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
|
||||
alloc_len = XCOPY_DESC_OFFSET +
|
||||
get_desc_len(IDENT_DESCR_TGT_DESCR) +
|
||||
get_desc_len(BLK_TO_BLK_SEG_DESCR);
|
||||
data.data = alloca(alloc_len);
|
||||
xcopybuf = data.data;
|
||||
|
||||
logging(LOG_VERBOSE,
|
||||
"Send Fibre Channel N_Port_Name target descriptor");
|
||||
data.size = init_xcopybuf(xcopybuf, 0xE0, BLK_TO_BLK_SEG_DESCR,
|
||||
&tgt_desc_len, &seg_desc_len);
|
||||
populate_param_header(xcopybuf, 1, 0, 0, 0,
|
||||
tgt_desc_len, seg_desc_len, 0);
|
||||
|
||||
ret = extendedcopy(sd, &data, EXPECT_UNSUPP_DESCR_CODE);
|
||||
if (ret == -2) {
|
||||
CU_PASS("[SKIPPED] Target does not support "
|
||||
"EXTENDED_COPY. Skipping test");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Send Stream-to-Stream Copy segment descriptor");
|
||||
memset(xcopybuf, 0, alloc_len);
|
||||
data.size = init_xcopybuf(xcopybuf, IDENT_DESCR_TGT_DESCR,
|
||||
STRM_TO_STRM_SEG_DESCR,
|
||||
&tgt_desc_len, &seg_desc_len);
|
||||
populate_param_header(xcopybuf, 1, 0, 0, 0,
|
||||
tgt_desc_len, seg_desc_len, 0);
|
||||
|
||||
ret = extendedcopy(sd, &data, EXPECT_UNSUPP_DESCR_CODE);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
83
test-tool/test_extendedcopy_param.c
Normal file
83
test-tool/test_extendedcopy_param.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
Copyright (c) 2015 SanDisk Corp.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include "scsi-lowlevel.h"
|
||||
#include "iscsi-test-cu.h"
|
||||
|
||||
void
|
||||
test_extendedcopy_param(void)
|
||||
{
|
||||
int ret;
|
||||
int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET;
|
||||
struct iscsi_data data;
|
||||
unsigned char *xcopybuf;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test EXTENDED COPY parameter list length");
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
|
||||
data.size = XCOPY_DESC_OFFSET +
|
||||
get_desc_len(IDENT_DESCR_TGT_DESCR) +
|
||||
get_desc_len(BLK_TO_BLK_SEG_DESCR);
|
||||
data.data = alloca(data.size);
|
||||
xcopybuf = data.data;
|
||||
|
||||
offset += populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
|
||||
LU_ID_TYPE_LUN, 0, 0, 0, 0, sd);
|
||||
tgt_desc_len = offset - XCOPY_DESC_OFFSET;
|
||||
|
||||
offset += populate_seg_desc_b2b(xcopybuf+offset, 0, 0, 0, 0,
|
||||
2048, 0, num_blocks - 2048);
|
||||
seg_desc_len = offset - XCOPY_DESC_OFFSET - tgt_desc_len;
|
||||
|
||||
populate_param_header(xcopybuf, 1, 0, 0, 0,
|
||||
tgt_desc_len, seg_desc_len, 0);
|
||||
|
||||
logging(LOG_VERBOSE,
|
||||
"Test parameter list length truncating target descriptor");
|
||||
data.size = XCOPY_DESC_OFFSET +
|
||||
get_desc_len(IDENT_DESCR_TGT_DESCR) - 1;
|
||||
ret = extendedcopy(sd, &data, EXPECT_PARAM_LIST_LEN_ERR);
|
||||
if (ret == -2) {
|
||||
CU_PASS("[SKIPPED] Target does not support "
|
||||
"EXTENDED_COPY. Skipping test");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE,
|
||||
"Test parameter list length truncating segment descriptor");
|
||||
data.size = XCOPY_DESC_OFFSET +
|
||||
get_desc_len(IDENT_DESCR_TGT_DESCR) +
|
||||
get_desc_len(BLK_TO_BLK_SEG_DESCR) - 1;
|
||||
ret = extendedcopy(sd, &data, EXPECT_PARAM_LIST_LEN_ERR);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Test parameter list length = 0");
|
||||
data.size = 0;
|
||||
ret = extendedcopy(sd, &data, EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
93
test-tool/test_extendedcopy_simple.c
Normal file
93
test-tool/test_extendedcopy_simple.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
Copyright (c) 2015 SanDisk Corp.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include "scsi-lowlevel.h"
|
||||
#include "iscsi-test-cu.h"
|
||||
|
||||
void
|
||||
test_extendedcopy_simple(void)
|
||||
{
|
||||
int ret;
|
||||
int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET;
|
||||
struct iscsi_data data;
|
||||
unsigned char *xcopybuf;
|
||||
unsigned char *buf1 = alloca(2048*block_size);
|
||||
unsigned char *buf2 = alloca(2048*block_size);
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE,
|
||||
"Test EXTENDED COPY of 2048 blocks from start of LUN to end of LUN");
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
|
||||
logging(LOG_VERBOSE, "Write 2048 blocks of 'A' at LBA:0");
|
||||
memset(buf1, 'A', 2048*block_size);
|
||||
ret = write16(sd, 0, 2048*block_size, block_size, 0, 0, 0, 0, 0,
|
||||
buf1, EXPECT_STATUS_GOOD);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] WRITE16 is not implemented.");
|
||||
CU_PASS("WRITE16 is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
data.size = XCOPY_DESC_OFFSET +
|
||||
get_desc_len(IDENT_DESCR_TGT_DESCR) +
|
||||
get_desc_len(BLK_TO_BLK_SEG_DESCR);
|
||||
data.data = alloca(data.size);
|
||||
xcopybuf = data.data;
|
||||
|
||||
/* Initialize target descriptor list with one target descriptor */
|
||||
offset += populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
|
||||
LU_ID_TYPE_LUN, 0, 0, 0, 0, sd);
|
||||
tgt_desc_len = offset - XCOPY_DESC_OFFSET;
|
||||
|
||||
/* Iniitialize segment descriptor list with one segment descriptor */
|
||||
offset += populate_seg_desc_b2b(xcopybuf+offset, 0, 0, 0, 0,
|
||||
2048, 0, num_blocks - 2048);
|
||||
seg_desc_len = offset - XCOPY_DESC_OFFSET - tgt_desc_len;
|
||||
|
||||
/* Initialize the parameter list header */
|
||||
populate_param_header(xcopybuf, 1, 0, LIST_ID_USAGE_DISCARD, 0,
|
||||
tgt_desc_len, seg_desc_len, 0);
|
||||
|
||||
ret = extendedcopy(sd, &data, EXPECT_STATUS_GOOD);
|
||||
if (ret == -2) {
|
||||
CU_PASS("[SKIPPED] Target does not support "
|
||||
"EXTENDED_COPY. Skipping test");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Read 2048 blocks from end of the LUN");
|
||||
ret = read16(sd, NULL, num_blocks - 2048, 2048*block_size,
|
||||
block_size, 0, 0, 0, 0, 0, buf2,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
ret = memcmp(buf1, buf2, 2048);
|
||||
if (ret != 0)
|
||||
CU_FAIL("Blocks were not copied correctly");
|
||||
}
|
||||
83
test-tool/test_extendedcopy_validate_seg_descr.c
Normal file
83
test-tool/test_extendedcopy_validate_seg_descr.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
Copyright (c) 2015 SanDisk Corp.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include "scsi-lowlevel.h"
|
||||
#include "iscsi-test-cu.h"
|
||||
|
||||
void
|
||||
test_extendedcopy_validate_seg_descr(void)
|
||||
{
|
||||
int ret;
|
||||
int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET;
|
||||
struct iscsi_data data;
|
||||
unsigned char *xcopybuf;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test EXTENDED COPY segment descriptor fields");
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
|
||||
data.size = XCOPY_DESC_OFFSET +
|
||||
get_desc_len(IDENT_DESCR_TGT_DESCR) +
|
||||
get_desc_len(BLK_TO_BLK_SEG_DESCR);
|
||||
data.data = alloca(data.size);
|
||||
xcopybuf = data.data;
|
||||
|
||||
logging(LOG_VERBOSE, "Send invalid target descriptor index");
|
||||
offset += populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
|
||||
LU_ID_TYPE_LUN, 0, 0, 0, 0, sd);
|
||||
tgt_desc_len = offset - XCOPY_DESC_OFFSET;
|
||||
/* Inaccessible DESTINATION TARGET DESCRIPTOR INDEX */
|
||||
offset += populate_seg_desc_b2b(xcopybuf+offset, 0, 0, 0, 1,
|
||||
2048, 0, num_blocks - 2048);
|
||||
seg_desc_len = offset - XCOPY_DESC_OFFSET - tgt_desc_len;
|
||||
populate_param_header(xcopybuf, 1, 0, 0, 0,
|
||||
tgt_desc_len, seg_desc_len, 0);
|
||||
|
||||
ret = extendedcopy(sd, &data, EXPECT_COPY_ABORTED);
|
||||
if (ret == -2) {
|
||||
CU_PASS("[SKIPPED] Target does not support "
|
||||
"EXTENDED_COPY. Skipping test");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE,
|
||||
"Number of copy blocks beyond destination block device capacity");
|
||||
memset(xcopybuf, 0, data.size);
|
||||
offset = XCOPY_DESC_OFFSET;
|
||||
offset += populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
|
||||
LU_ID_TYPE_LUN, 0, 0, 0, 0, sd);
|
||||
tgt_desc_len = offset - XCOPY_DESC_OFFSET;
|
||||
/* Beyond EOL */
|
||||
offset += populate_seg_desc_b2b(xcopybuf+offset, 0, 0, 0, 0,
|
||||
2048, 0, num_blocks - 1);
|
||||
seg_desc_len = offset - XCOPY_DESC_OFFSET - tgt_desc_len;
|
||||
populate_param_header(xcopybuf, 1, 0, 0, 0,
|
||||
tgt_desc_len, seg_desc_len, 0);
|
||||
|
||||
ret = extendedcopy(sd, &data, EXPECT_COPY_ABORTED);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
82
test-tool/test_extendedcopy_validate_tgt_descr.c
Normal file
82
test-tool/test_extendedcopy_validate_tgt_descr.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright (c) 2015 SanDisk Corp.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include "scsi-lowlevel.h"
|
||||
#include "iscsi-test-cu.h"
|
||||
|
||||
void
|
||||
test_extendedcopy_validate_tgt_descr(void)
|
||||
{
|
||||
int ret;
|
||||
int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET;
|
||||
struct iscsi_data data;
|
||||
unsigned char *xcopybuf;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test EXTENDED COPY target descriptor fields");
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
|
||||
data.size = XCOPY_DESC_OFFSET +
|
||||
get_desc_len(IDENT_DESCR_TGT_DESCR) +
|
||||
get_desc_len(BLK_TO_BLK_SEG_DESCR);
|
||||
data.data = alloca(data.size);
|
||||
xcopybuf = data.data;
|
||||
|
||||
logging(LOG_VERBOSE, "Unsupported LU_ID TYPE");
|
||||
/* Unsupported LU ID TYPE */
|
||||
offset += populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
|
||||
LU_ID_TYPE_RSVD, 0, 0, 0, 0, sd);
|
||||
tgt_desc_len = offset - XCOPY_DESC_OFFSET;
|
||||
offset += populate_seg_desc_b2b(xcopybuf+offset, 0, 0, 0, 0,
|
||||
2048, 0, num_blocks - 2048);
|
||||
seg_desc_len = offset - XCOPY_DESC_OFFSET - tgt_desc_len;
|
||||
populate_param_header(xcopybuf, 1, 0, 0, 0,
|
||||
tgt_desc_len, seg_desc_len, 0);
|
||||
|
||||
ret = extendedcopy(sd, &data, EXPECT_INVALID_FIELD_IN_CDB);
|
||||
if (ret == -2) {
|
||||
CU_PASS("[SKIPPED] Target does not support "
|
||||
"EXTENDED_COPY. Skipping test");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Test NUL bit in target descriptor");
|
||||
/* NUL bit */
|
||||
memset(xcopybuf, 0, data.size);
|
||||
offset = XCOPY_DESC_OFFSET;
|
||||
offset += populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
|
||||
LU_ID_TYPE_LUN, 1, 0, 0, 0, sd);
|
||||
tgt_desc_len = offset - XCOPY_DESC_OFFSET;
|
||||
offset += populate_seg_desc_b2b(xcopybuf+offset, 0, 0, 0, 0,
|
||||
2048, 0, num_blocks - 2048);
|
||||
seg_desc_len = offset - XCOPY_DESC_OFFSET - tgt_desc_len;
|
||||
populate_param_header(xcopybuf, 1, 0, 0, 0,
|
||||
tgt_desc_len, seg_desc_len, 0);
|
||||
|
||||
ret = extendedcopy(sd, &data, EXPECT_COPY_ABORTED);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
83
test-tool/test_receive_copy_results_copy_status.c
Normal file
83
test-tool/test_receive_copy_results_copy_status.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
Copyright (c) 2015 SanDisk Corp.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include "scsi-lowlevel.h"
|
||||
#include "iscsi-test-cu.h"
|
||||
|
||||
void
|
||||
test_receive_copy_results_copy_status(void)
|
||||
{
|
||||
int ret;
|
||||
struct scsi_copy_results_copy_status *csp;
|
||||
int tgt_desc_len = 0, seg_desc_len = 0;
|
||||
int offset = XCOPY_DESC_OFFSET, list_id = 1;
|
||||
struct iscsi_data data;
|
||||
unsigned char *xcopybuf;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test RECEIVE COPY RESULTS, COPY STATUS");
|
||||
|
||||
logging(LOG_VERBOSE, "No copy in progress");
|
||||
ret = receive_copy_results(sd, SCSI_COPY_RESULTS_COPY_STATUS,
|
||||
list_id, NULL, EXPECT_INVALID_FIELD_IN_CDB);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
|
||||
logging(LOG_VERBOSE, "Issue Extended Copy");
|
||||
data.size = XCOPY_DESC_OFFSET +
|
||||
get_desc_len(IDENT_DESCR_TGT_DESCR) +
|
||||
get_desc_len(BLK_TO_BLK_SEG_DESCR);
|
||||
data.data = alloca(data.size);
|
||||
xcopybuf = data.data;
|
||||
|
||||
/* Initialize target descriptor list with one target descriptor */
|
||||
offset += populate_tgt_desc(xcopybuf+offset, IDENT_DESCR_TGT_DESCR,
|
||||
LU_ID_TYPE_LUN, 0, 0, 0, 0, sd);
|
||||
tgt_desc_len = offset - XCOPY_DESC_OFFSET;
|
||||
|
||||
/* Iniitialize segment descriptor list with one segment descriptor */
|
||||
offset += populate_seg_desc_b2b(xcopybuf+offset, 0, 0, 0, 0,
|
||||
2048, 0, num_blocks - 2048);
|
||||
seg_desc_len = offset - XCOPY_DESC_OFFSET - tgt_desc_len;
|
||||
|
||||
/* Initialize the parameter list header */
|
||||
populate_param_header(xcopybuf, list_id, 0, 0, 0,
|
||||
tgt_desc_len, seg_desc_len, 0);
|
||||
|
||||
ret = extendedcopy(sd, &data, EXPECT_STATUS_GOOD);
|
||||
if (ret == -2) {
|
||||
CU_PASS("[SKIPPED] Target does not support "
|
||||
"EXTENDED_COPY. Skipping test");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE,
|
||||
"Copy Status for the above Extended Copy command");
|
||||
ret = receive_copy_results(sd, SCSI_COPY_RESULTS_COPY_STATUS,
|
||||
list_id, (void **)&csp, EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
46
test-tool/test_receive_copy_results_op_params.c
Normal file
46
test-tool/test_receive_copy_results_op_params.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright (c) 2015 SanDisk Corp.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include "scsi-lowlevel.h"
|
||||
#include "iscsi-test-cu.h"
|
||||
|
||||
void
|
||||
test_receive_copy_results_op_params(void)
|
||||
{
|
||||
int ret;
|
||||
struct scsi_copy_results_op_params *opp;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test RECEIVE COPY RESULTS, OPERATING PARAMS");
|
||||
|
||||
ret = receive_copy_results(sd, SCSI_COPY_RESULTS_OP_PARAMS, 0,
|
||||
(void **)&opp, EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_NORMAL,
|
||||
"max_target_desc=%d, max_seg_desc=%d",
|
||||
opp->max_target_desc_count,
|
||||
opp->max_segment_desc_count);
|
||||
}
|
||||
Reference in New Issue
Block a user