Tests: convert tabs to 8 spaces
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
This commit is contained in:
@@ -54,338 +54,338 @@ struct scsi_device *mp_sds[MPATH_MAX_DEVS];
|
||||
static void
|
||||
mpath_des_free(struct scsi_inquiry_device_designator *des)
|
||||
{
|
||||
if (!des) {
|
||||
return;
|
||||
}
|
||||
if (!des) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(des->designator);
|
||||
free(des);
|
||||
free(des->designator);
|
||||
free(des);
|
||||
}
|
||||
|
||||
static int
|
||||
mpath_des_copy(struct scsi_inquiry_device_designator *des,
|
||||
struct scsi_inquiry_device_designator **_des_cp)
|
||||
struct scsi_inquiry_device_designator **_des_cp)
|
||||
{
|
||||
struct scsi_inquiry_device_designator *des_cp;
|
||||
struct scsi_inquiry_device_designator *des_cp;
|
||||
|
||||
if (!_des_cp) {
|
||||
return -1;
|
||||
}
|
||||
if (!_des_cp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
des_cp = malloc(sizeof(*des_cp));
|
||||
if (des_cp == NULL) {
|
||||
return -1;
|
||||
}
|
||||
des_cp = malloc(sizeof(*des_cp));
|
||||
if (des_cp == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
des_cp->protocol_identifier = des->protocol_identifier;
|
||||
des_cp->code_set = des->code_set;
|
||||
des_cp->piv = des->piv;
|
||||
des_cp->association = des->association;
|
||||
des_cp->designator_type = des->designator_type;
|
||||
des_cp->designator_length = des->designator_length;
|
||||
des_cp->designator = malloc(des->designator_length);
|
||||
if (des_cp->designator == NULL) {
|
||||
free(des_cp);
|
||||
return -1;
|
||||
}
|
||||
memcpy(des_cp->designator, des->designator, des->designator_length);
|
||||
*_des_cp = des_cp;
|
||||
des_cp->protocol_identifier = des->protocol_identifier;
|
||||
des_cp->code_set = des->code_set;
|
||||
des_cp->piv = des->piv;
|
||||
des_cp->association = des->association;
|
||||
des_cp->designator_type = des->designator_type;
|
||||
des_cp->designator_length = des->designator_length;
|
||||
des_cp->designator = malloc(des->designator_length);
|
||||
if (des_cp->designator == NULL) {
|
||||
free(des_cp);
|
||||
return -1;
|
||||
}
|
||||
memcpy(des_cp->designator, des->designator, des->designator_length);
|
||||
*_des_cp = des_cp;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mpath_des_cmp(struct scsi_inquiry_device_designator *des1,
|
||||
struct scsi_inquiry_device_designator *des2)
|
||||
struct scsi_inquiry_device_designator *des2)
|
||||
{
|
||||
if (des1->protocol_identifier != des2->protocol_identifier) {
|
||||
return -1;
|
||||
}
|
||||
if (des1->protocol_identifier != des2->protocol_identifier) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (des1->code_set != des2->code_set) {
|
||||
return -1;
|
||||
}
|
||||
if (des1->code_set != des2->code_set) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (des1->piv != des2->piv) {
|
||||
return -1;
|
||||
}
|
||||
if (des1->piv != des2->piv) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (des1->association != des2->association) {
|
||||
return -1;
|
||||
}
|
||||
if (des1->association != des2->association) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (des1->designator_type != des2->designator_type) {
|
||||
return -1;
|
||||
}
|
||||
if (des1->designator_type != des2->designator_type) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (des1->designator_length != des2->designator_length) {
|
||||
return -1;
|
||||
}
|
||||
if (des1->designator_length != des2->designator_length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return memcmp(des1->designator, des2->designator,
|
||||
des1->designator_length);
|
||||
return memcmp(des1->designator, des2->designator,
|
||||
des1->designator_length);
|
||||
}
|
||||
|
||||
static int
|
||||
mpath_check_matching_ids_devid_vpd(int num_sds,
|
||||
struct scsi_device **sds)
|
||||
struct scsi_device **sds)
|
||||
{
|
||||
int i;
|
||||
int num_sds_with_valid_id = 0;
|
||||
struct scsi_task *inq_task = NULL;
|
||||
struct scsi_inquiry_device_designator *des_saved = NULL;
|
||||
int i;
|
||||
int num_sds_with_valid_id = 0;
|
||||
struct scsi_task *inq_task = NULL;
|
||||
struct scsi_inquiry_device_designator *des_saved = NULL;
|
||||
|
||||
for (i = 0; i < num_sds; i++) {
|
||||
int ret;
|
||||
int full_size;
|
||||
struct scsi_inquiry_device_identification *inq_id_data;
|
||||
struct scsi_inquiry_device_designator *des;
|
||||
for (i = 0; i < num_sds; i++) {
|
||||
int ret;
|
||||
int full_size;
|
||||
struct scsi_inquiry_device_identification *inq_id_data;
|
||||
struct scsi_inquiry_device_designator *des;
|
||||
|
||||
/*
|
||||
* dev ID inquiry to confirm that all multipath devices carry
|
||||
* an identical logical unit identifier.
|
||||
*/
|
||||
inquiry(sds[i], &inq_task, 1,
|
||||
SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION,
|
||||
64,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (inq_task == NULL || inq_task->status != SCSI_STATUS_GOOD) {
|
||||
printf("Inquiry command failed : %s\n",
|
||||
sds[i]->error_str);
|
||||
goto err_cleanup;
|
||||
}
|
||||
full_size = scsi_datain_getfullsize(inq_task);
|
||||
if (full_size > inq_task->datain.size) {
|
||||
/* we need more data */
|
||||
scsi_free_scsi_task(inq_task);
|
||||
inq_task = NULL;
|
||||
inquiry(sds[i], &inq_task, 1,
|
||||
SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION,
|
||||
full_size,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (inq_task == NULL) {
|
||||
printf("Inquiry command failed : %s\n",
|
||||
sds[i]->error_str);
|
||||
goto err_cleanup;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* dev ID inquiry to confirm that all multipath devices carry
|
||||
* an identical logical unit identifier.
|
||||
*/
|
||||
inquiry(sds[i], &inq_task, 1,
|
||||
SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION,
|
||||
64,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (inq_task == NULL || inq_task->status != SCSI_STATUS_GOOD) {
|
||||
printf("Inquiry command failed : %s\n",
|
||||
sds[i]->error_str);
|
||||
goto err_cleanup;
|
||||
}
|
||||
full_size = scsi_datain_getfullsize(inq_task);
|
||||
if (full_size > inq_task->datain.size) {
|
||||
/* we need more data */
|
||||
scsi_free_scsi_task(inq_task);
|
||||
inq_task = NULL;
|
||||
inquiry(sds[i], &inq_task, 1,
|
||||
SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION,
|
||||
full_size,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (inq_task == NULL) {
|
||||
printf("Inquiry command failed : %s\n",
|
||||
sds[i]->error_str);
|
||||
goto err_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
inq_id_data = scsi_datain_unmarshall(inq_task);
|
||||
if (inq_id_data == NULL) {
|
||||
printf("failed to unmarshall inquiry ID datain blob\n");
|
||||
goto err_cleanup;
|
||||
}
|
||||
inq_id_data = scsi_datain_unmarshall(inq_task);
|
||||
if (inq_id_data == NULL) {
|
||||
printf("failed to unmarshall inquiry ID datain blob\n");
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
if (inq_id_data->qualifier
|
||||
!= SCSI_INQUIRY_PERIPHERAL_QUALIFIER_CONNECTED) {
|
||||
printf("error: multipath device not connected\n");
|
||||
goto err_cleanup;
|
||||
}
|
||||
if (inq_id_data->qualifier
|
||||
!= SCSI_INQUIRY_PERIPHERAL_QUALIFIER_CONNECTED) {
|
||||
printf("error: multipath device not connected\n");
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
if (inq_id_data->device_type
|
||||
!= SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {
|
||||
printf("error: multipath devices must be SBC\n");
|
||||
goto err_cleanup;
|
||||
}
|
||||
if (inq_id_data->device_type
|
||||
!= SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {
|
||||
printf("error: multipath devices must be SBC\n");
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
/* walk the list of IDs, and find a suitable LU candidate */
|
||||
for (des = inq_id_data->designators;
|
||||
des != NULL;
|
||||
des = des->next) {
|
||||
if (des->association != SCSI_ASSOCIATION_LOGICAL_UNIT) {
|
||||
printf("skipping non-LU designator: %d\n",
|
||||
des->association);
|
||||
continue;
|
||||
}
|
||||
/* walk the list of IDs, and find a suitable LU candidate */
|
||||
for (des = inq_id_data->designators;
|
||||
des != NULL;
|
||||
des = des->next) {
|
||||
if (des->association != SCSI_ASSOCIATION_LOGICAL_UNIT) {
|
||||
printf("skipping non-LU designator: %d\n",
|
||||
des->association);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((des->designator_type != SCSI_DESIGNATOR_TYPE_EUI_64)
|
||||
&& (des->designator_type != SCSI_DESIGNATOR_TYPE_NAA)
|
||||
&& (des->designator_type != SCSI_DESIGNATOR_TYPE_MD5_LOGICAL_UNIT_IDENTIFIER)
|
||||
&& (des->designator_type != SCSI_DESIGNATOR_TYPE_SCSI_NAME_STRING)) {
|
||||
printf("skipping unsupported des type: %d\n",
|
||||
des->designator_type);
|
||||
continue;
|
||||
}
|
||||
if ((des->designator_type != SCSI_DESIGNATOR_TYPE_EUI_64)
|
||||
&& (des->designator_type != SCSI_DESIGNATOR_TYPE_NAA)
|
||||
&& (des->designator_type != SCSI_DESIGNATOR_TYPE_MD5_LOGICAL_UNIT_IDENTIFIER)
|
||||
&& (des->designator_type != SCSI_DESIGNATOR_TYPE_SCSI_NAME_STRING)) {
|
||||
printf("skipping unsupported des type: %d\n",
|
||||
des->designator_type);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (des->designator_length <= 0) {
|
||||
printf("skipping designator with bad len: %d\n",
|
||||
des->designator_length);
|
||||
continue;
|
||||
}
|
||||
if (des->designator_length <= 0) {
|
||||
printf("skipping designator with bad len: %d\n",
|
||||
des->designator_length);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (des_saved == NULL) {
|
||||
ret = mpath_des_copy(des, &des_saved);
|
||||
if (ret < 0) {
|
||||
goto err_cleanup;
|
||||
}
|
||||
/*
|
||||
* we now have a reference to look for in all
|
||||
* subsequent paths.
|
||||
*/
|
||||
num_sds_with_valid_id++;
|
||||
break;
|
||||
} else if (mpath_des_cmp(des, des_saved) == 0) {
|
||||
/* found match for previous path designator */
|
||||
num_sds_with_valid_id++;
|
||||
break;
|
||||
}
|
||||
/* no match yet, keep checking other designators */
|
||||
}
|
||||
if (des_saved == NULL) {
|
||||
ret = mpath_des_copy(des, &des_saved);
|
||||
if (ret < 0) {
|
||||
goto err_cleanup;
|
||||
}
|
||||
/*
|
||||
* we now have a reference to look for in all
|
||||
* subsequent paths.
|
||||
*/
|
||||
num_sds_with_valid_id++;
|
||||
break;
|
||||
} else if (mpath_des_cmp(des, des_saved) == 0) {
|
||||
/* found match for previous path designator */
|
||||
num_sds_with_valid_id++;
|
||||
break;
|
||||
}
|
||||
/* no match yet, keep checking other designators */
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(inq_task);
|
||||
inq_task = NULL;
|
||||
}
|
||||
mpath_des_free(des_saved);
|
||||
scsi_free_scsi_task(inq_task);
|
||||
inq_task = NULL;
|
||||
}
|
||||
mpath_des_free(des_saved);
|
||||
|
||||
if (num_sds_with_valid_id != num_sds) {
|
||||
printf("failed to find matching LU device ID for all paths\n");
|
||||
return -1;
|
||||
}
|
||||
if (num_sds_with_valid_id != num_sds) {
|
||||
printf("failed to find matching LU device ID for all paths\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("found matching LU device identifier for all (%d) paths\n",
|
||||
num_sds);
|
||||
return 0;
|
||||
printf("found matching LU device identifier for all (%d) paths\n",
|
||||
num_sds);
|
||||
return 0;
|
||||
|
||||
err_cleanup:
|
||||
mpath_des_free(des_saved);
|
||||
scsi_free_scsi_task(inq_task);
|
||||
return -1;
|
||||
mpath_des_free(des_saved);
|
||||
scsi_free_scsi_task(inq_task);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
mpath_check_matching_ids_serial_vpd(int num_sds,
|
||||
struct scsi_device **sds)
|
||||
struct scsi_device **sds)
|
||||
{
|
||||
int i;
|
||||
int num_sds_with_valid_id = 0;
|
||||
struct scsi_task *inq_task = NULL;
|
||||
char *usn_saved = NULL;
|
||||
int i;
|
||||
int num_sds_with_valid_id = 0;
|
||||
struct scsi_task *inq_task = NULL;
|
||||
char *usn_saved = NULL;
|
||||
|
||||
for (i = 0; i < num_sds; i++) {
|
||||
int full_size;
|
||||
struct scsi_inquiry_unit_serial_number *inq_serial;
|
||||
for (i = 0; i < num_sds; i++) {
|
||||
int full_size;
|
||||
struct scsi_inquiry_unit_serial_number *inq_serial;
|
||||
|
||||
/*
|
||||
* inquiry to confirm that all multipath devices carry an
|
||||
* identical unit serial number.
|
||||
*/
|
||||
inq_task = NULL;
|
||||
inquiry(sds[i], &inq_task, 1,
|
||||
SCSI_INQUIRY_PAGECODE_UNIT_SERIAL_NUMBER, 64,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (inq_task == NULL || inq_task->status != SCSI_STATUS_GOOD) {
|
||||
printf("Inquiry command failed : %s\n",
|
||||
sds[i]->error_str);
|
||||
goto err_cleanup;
|
||||
}
|
||||
full_size = scsi_datain_getfullsize(inq_task);
|
||||
if (full_size > inq_task->datain.size) {
|
||||
scsi_free_scsi_task(inq_task);
|
||||
/*
|
||||
* inquiry to confirm that all multipath devices carry an
|
||||
* identical unit serial number.
|
||||
*/
|
||||
inq_task = NULL;
|
||||
inquiry(sds[i], &inq_task, 1,
|
||||
SCSI_INQUIRY_PAGECODE_UNIT_SERIAL_NUMBER, 64,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (inq_task == NULL || inq_task->status != SCSI_STATUS_GOOD) {
|
||||
printf("Inquiry command failed : %s\n",
|
||||
sds[i]->error_str);
|
||||
goto err_cleanup;
|
||||
}
|
||||
full_size = scsi_datain_getfullsize(inq_task);
|
||||
if (full_size > inq_task->datain.size) {
|
||||
scsi_free_scsi_task(inq_task);
|
||||
|
||||
/* we need more data */
|
||||
inq_task = NULL;
|
||||
inquiry(sds[i], &inq_task, 1,
|
||||
SCSI_INQUIRY_PAGECODE_UNIT_SERIAL_NUMBER,
|
||||
full_size,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (inq_task == NULL) {
|
||||
printf("Inquiry command failed : %s\n",
|
||||
sds[i]->error_str);
|
||||
goto err_cleanup;
|
||||
}
|
||||
}
|
||||
/* we need more data */
|
||||
inq_task = NULL;
|
||||
inquiry(sds[i], &inq_task, 1,
|
||||
SCSI_INQUIRY_PAGECODE_UNIT_SERIAL_NUMBER,
|
||||
full_size,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (inq_task == NULL) {
|
||||
printf("Inquiry command failed : %s\n",
|
||||
sds[i]->error_str);
|
||||
goto err_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
inq_serial = scsi_datain_unmarshall(inq_task);
|
||||
if (inq_serial == NULL) {
|
||||
printf("failed to unmarshall inquiry datain blob\n");
|
||||
goto err_cleanup;
|
||||
}
|
||||
inq_serial = scsi_datain_unmarshall(inq_task);
|
||||
if (inq_serial == NULL) {
|
||||
printf("failed to unmarshall inquiry datain blob\n");
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
if (inq_serial->qualifier
|
||||
!= SCSI_INQUIRY_PERIPHERAL_QUALIFIER_CONNECTED) {
|
||||
printf("error: multipath device not connected\n");
|
||||
goto err_cleanup;
|
||||
}
|
||||
if (inq_serial->qualifier
|
||||
!= SCSI_INQUIRY_PERIPHERAL_QUALIFIER_CONNECTED) {
|
||||
printf("error: multipath device not connected\n");
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
if (inq_serial->device_type
|
||||
!= SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {
|
||||
printf("error: multipath devices must be SBC\n");
|
||||
goto err_cleanup;
|
||||
}
|
||||
if (inq_serial->device_type
|
||||
!= SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {
|
||||
printf("error: multipath devices must be SBC\n");
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
if (inq_serial->usn == NULL) {
|
||||
printf("error: empty usn for multipath device\n");
|
||||
goto err_cleanup;
|
||||
}
|
||||
if (inq_serial->usn == NULL) {
|
||||
printf("error: empty usn for multipath device\n");
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
if (usn_saved == NULL) {
|
||||
usn_saved = strdup(inq_serial->usn);
|
||||
if (usn_saved == NULL) {
|
||||
goto err_cleanup;
|
||||
}
|
||||
num_sds_with_valid_id++;
|
||||
} else if (strcmp(usn_saved, inq_serial->usn) == 0) {
|
||||
num_sds_with_valid_id++;
|
||||
} else {
|
||||
printf("multipath unit serial mismatch: %s != %s\n",
|
||||
usn_saved, inq_serial->usn);
|
||||
}
|
||||
if (usn_saved == NULL) {
|
||||
usn_saved = strdup(inq_serial->usn);
|
||||
if (usn_saved == NULL) {
|
||||
goto err_cleanup;
|
||||
}
|
||||
num_sds_with_valid_id++;
|
||||
} else if (strcmp(usn_saved, inq_serial->usn) == 0) {
|
||||
num_sds_with_valid_id++;
|
||||
} else {
|
||||
printf("multipath unit serial mismatch: %s != %s\n",
|
||||
usn_saved, inq_serial->usn);
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(inq_task);
|
||||
inq_task = NULL;
|
||||
}
|
||||
scsi_free_scsi_task(inq_task);
|
||||
inq_task = NULL;
|
||||
}
|
||||
|
||||
if (num_sds_with_valid_id != num_sds) {
|
||||
printf("failed to find matching serial number for all paths\n");
|
||||
goto err_cleanup;
|
||||
}
|
||||
if (num_sds_with_valid_id != num_sds) {
|
||||
printf("failed to find matching serial number for all paths\n");
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
printf("found matching serial number for all (%d) paths: %s\n",
|
||||
num_sds, usn_saved);
|
||||
free(usn_saved);
|
||||
printf("found matching serial number for all (%d) paths: %s\n",
|
||||
num_sds, usn_saved);
|
||||
free(usn_saved);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
err_cleanup:
|
||||
free(usn_saved);
|
||||
scsi_free_scsi_task(inq_task);
|
||||
return -1;
|
||||
free(usn_saved);
|
||||
scsi_free_scsi_task(inq_task);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
mpath_check_matching_ids(int num_sds,
|
||||
struct scsi_device **sds)
|
||||
struct scsi_device **sds)
|
||||
{
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* first check all devices for a matching LU identifier in the device
|
||||
* identification INQUIRY VPD page.
|
||||
*/
|
||||
ret = mpath_check_matching_ids_devid_vpd(num_sds, sds);
|
||||
if (ret == 0) {
|
||||
return 0; /* found matching */
|
||||
}
|
||||
/*
|
||||
* first check all devices for a matching LU identifier in the device
|
||||
* identification INQUIRY VPD page.
|
||||
*/
|
||||
ret = mpath_check_matching_ids_devid_vpd(num_sds, sds);
|
||||
if (ret == 0) {
|
||||
return 0; /* found matching */
|
||||
}
|
||||
|
||||
/* fall back to a unit serial number check */
|
||||
ret = mpath_check_matching_ids_serial_vpd(num_sds, sds);
|
||||
return ret;
|
||||
/* fall back to a unit serial number check */
|
||||
ret = mpath_check_matching_ids_serial_vpd(num_sds, sds);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
mpath_count_iscsi(int num_sds,
|
||||
struct scsi_device **sds)
|
||||
struct scsi_device **sds)
|
||||
{
|
||||
int i;
|
||||
int found = 0;
|
||||
int i;
|
||||
int found = 0;
|
||||
|
||||
for (i = 0; i < num_sds; i++) {
|
||||
if (sds[i]->iscsi_ctx != NULL) {
|
||||
found++;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < num_sds; i++) {
|
||||
if (sds[i]->iscsi_ctx != NULL) {
|
||||
found++;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
return found;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -394,52 +394,52 @@ mpath_count_iscsi(int num_sds,
|
||||
int
|
||||
mpath_sd2_get_or_clone(struct scsi_device *sd1, struct scsi_device **_sd2)
|
||||
{
|
||||
struct scsi_device *sd2;
|
||||
struct scsi_device *sd2;
|
||||
|
||||
if (mp_num_sds > 1) {
|
||||
logging(LOG_VERBOSE, "using multipath dev for second session");
|
||||
*_sd2 = mp_sds[1];
|
||||
return 0;
|
||||
}
|
||||
if (mp_num_sds > 1) {
|
||||
logging(LOG_VERBOSE, "using multipath dev for second session");
|
||||
*_sd2 = mp_sds[1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sd1->iscsi_ctx == NULL) {
|
||||
logging(LOG_NORMAL, "can't clone non-iscsi device");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (sd1->iscsi_ctx == NULL) {
|
||||
logging(LOG_NORMAL, "can't clone non-iscsi device");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "cloning sd1 for second session");
|
||||
sd2 = malloc(sizeof(*sd2));
|
||||
if (sd2 == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
logging(LOG_VERBOSE, "cloning sd1 for second session");
|
||||
sd2 = malloc(sizeof(*sd2));
|
||||
if (sd2 == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(sd2, 0, sizeof(*sd2));
|
||||
sd2->iscsi_url = sd1->iscsi_url;
|
||||
sd2->iscsi_lun = sd1->iscsi_lun;
|
||||
sd2->iscsi_ctx = iscsi_context_login(initiatorname2, sd2->iscsi_url,
|
||||
&sd2->iscsi_lun);
|
||||
if (sd2->iscsi_ctx == NULL) {
|
||||
logging(LOG_VERBOSE, "Failed to login to target");
|
||||
free(sd2);
|
||||
return -ENOMEM;
|
||||
}
|
||||
*_sd2 = sd2;
|
||||
memset(sd2, 0, sizeof(*sd2));
|
||||
sd2->iscsi_url = sd1->iscsi_url;
|
||||
sd2->iscsi_lun = sd1->iscsi_lun;
|
||||
sd2->iscsi_ctx = iscsi_context_login(initiatorname2, sd2->iscsi_url,
|
||||
&sd2->iscsi_lun);
|
||||
if (sd2->iscsi_ctx == NULL) {
|
||||
logging(LOG_VERBOSE, "Failed to login to target");
|
||||
free(sd2);
|
||||
return -ENOMEM;
|
||||
}
|
||||
*_sd2 = sd2;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
mpath_sd2_put(struct scsi_device *sd2)
|
||||
{
|
||||
if (mp_num_sds > 1) {
|
||||
if (sd2 != mp_sds[1]) {
|
||||
logging(LOG_NORMAL, "Invalid sd2!");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (mp_num_sds > 1) {
|
||||
if (sd2 != mp_sds[1]) {
|
||||
logging(LOG_NORMAL, "Invalid sd2!");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* sd2 was allocated by mp_get - cleanup */
|
||||
iscsi_logout_sync(sd2->iscsi_ctx);
|
||||
iscsi_destroy_context(sd2->iscsi_ctx);
|
||||
free(sd2);
|
||||
/* sd2 was allocated by mp_get - cleanup */
|
||||
iscsi_logout_sync(sd2->iscsi_ctx);
|
||||
iscsi_destroy_context(sd2->iscsi_ctx);
|
||||
free(sd2);
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ISCSI_MULTIPATH_H_
|
||||
#define _ISCSI_MULTIPATH_H_
|
||||
#ifndef _ISCSI_MULTIPATH_H_
|
||||
#define _ISCSI_MULTIPATH_H_
|
||||
|
||||
#define MPATH_MAX_DEVS 2
|
||||
extern int mp_num_sds;
|
||||
@@ -26,35 +26,35 @@ extern struct scsi_device *mp_sds[MPATH_MAX_DEVS];
|
||||
|
||||
int
|
||||
mpath_check_matching_ids(int num_sds,
|
||||
struct scsi_device **sds);
|
||||
struct scsi_device **sds);
|
||||
int
|
||||
mpath_count_iscsi(int num_sds,
|
||||
struct scsi_device **sds);
|
||||
struct scsi_device **sds);
|
||||
int
|
||||
mpath_sd2_get_or_clone(struct scsi_device *sd1, struct scsi_device **_sd2);
|
||||
void
|
||||
mpath_sd2_put(struct scsi_device *sd2);
|
||||
|
||||
#define MPATH_SKIP_IF_UNAVAILABLE(_sds, _num_sds) \
|
||||
do { \
|
||||
if (_num_sds <= 1) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] Multipath unavailable." \
|
||||
" Skipping test"); \
|
||||
CU_PASS("[SKIPPED] Multipath unavailable." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
#define MPATH_SKIP_IF_UNAVAILABLE(_sds, _num_sds) \
|
||||
do { \
|
||||
if (_num_sds <= 1) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] Multipath unavailable." \
|
||||
" Skipping test"); \
|
||||
CU_PASS("[SKIPPED] Multipath unavailable." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define MPATH_SKIP_UNLESS_ISCSI(_sds, _num_sds) \
|
||||
do { \
|
||||
if (mpath_count_iscsi(_num_sds, _sds) != _num_sds) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] Non-iSCSI multipath." \
|
||||
" Skipping test"); \
|
||||
CU_PASS("[SKIPPED] Non-iSCSI multipath." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
#define MPATH_SKIP_UNLESS_ISCSI(_sds, _num_sds) \
|
||||
do { \
|
||||
if (mpath_count_iscsi(_num_sds, _sds) != _num_sds) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] Non-iSCSI multipath." \
|
||||
" Skipping test"); \
|
||||
CU_PASS("[SKIPPED] Non-iSCSI multipath." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#endif /* _ISCSI_MULTIPATH_H_ */
|
||||
#endif /* _ISCSI_MULTIPATH_H_ */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,8 +18,8 @@
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ISCSI_SUPPORT_H_
|
||||
#define _ISCSI_SUPPORT_H_
|
||||
#ifndef _ISCSI_SUPPORT_H_
|
||||
#define _ISCSI_SUPPORT_H_
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
@@ -70,115 +70,115 @@ void logging(int level, const char *format, ...) _R_(2,3);
|
||||
* define special flags for logging a blank line, so compiler
|
||||
* does not commplain when logging a ""
|
||||
*/
|
||||
#define LOG_BLANK_LINE " "
|
||||
#define LOG_BLANK_LINE " "
|
||||
#define LOG_BLANK_LINE_CMP_LEN 2
|
||||
|
||||
#define CHECK_FOR_DATALOSS \
|
||||
do { \
|
||||
if (!data_loss) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] --dataloss flag is not " \
|
||||
"set. Skipping test."); \
|
||||
CU_PASS("[SKIPPED] --dataloss flag is not set." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
#define CHECK_FOR_DATALOSS \
|
||||
do { \
|
||||
if (!data_loss) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] --dataloss flag is not " \
|
||||
"set. Skipping test."); \
|
||||
CU_PASS("[SKIPPED] --dataloss flag is not set." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define CHECK_FOR_SANITIZE \
|
||||
do { \
|
||||
if (!allow_sanitize) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] --allow-sanitize flag " \
|
||||
"is not set. Skipping test."); \
|
||||
CU_PASS("[SKIPPED] --allow-sanitize flag is not set." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
#define CHECK_FOR_SANITIZE \
|
||||
do { \
|
||||
if (!allow_sanitize) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] --allow-sanitize flag " \
|
||||
"is not set. Skipping test."); \
|
||||
CU_PASS("[SKIPPED] --allow-sanitize flag is not set." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define CHECK_FOR_READONLY \
|
||||
do { \
|
||||
if (!readonly) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] Logical unit is not " \
|
||||
"write-protected. Skipping test."); \
|
||||
CU_PASS("[SKIPPED] Logical unit is not write-" \
|
||||
"protected. Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
#define CHECK_FOR_READONLY \
|
||||
do { \
|
||||
if (!readonly) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] Logical unit is not " \
|
||||
"write-protected. Skipping test."); \
|
||||
CU_PASS("[SKIPPED] Logical unit is not write-" \
|
||||
"protected. Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define CHECK_FOR_REMOVABLE \
|
||||
do { \
|
||||
if (!inq->rmb) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] Logical unit is not " \
|
||||
"removable. Skipping test."); \
|
||||
CU_PASS("[SKIPPED] Logical unit is not removable" \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
#define CHECK_FOR_REMOVABLE \
|
||||
do { \
|
||||
if (!inq->rmb) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] Logical unit is not " \
|
||||
"removable. Skipping test."); \
|
||||
CU_PASS("[SKIPPED] Logical unit is not removable" \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define CHECK_FOR_THIN_PROVISIONING \
|
||||
do { \
|
||||
if (rc16 == NULL || rc16->lbpme == 0) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] Logical unit is fully" \
|
||||
" provisioned. Skipping test"); \
|
||||
CU_PASS("[SKIPPED] Logical unit is fully provisioned." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
#define CHECK_FOR_THIN_PROVISIONING \
|
||||
do { \
|
||||
if (rc16 == NULL || rc16->lbpme == 0) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] Logical unit is fully" \
|
||||
" provisioned. Skipping test"); \
|
||||
CU_PASS("[SKIPPED] Logical unit is fully provisioned." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define CHECK_FOR_LBPWS10 \
|
||||
do { \
|
||||
if (inq_lbp->lbpws10 == 0) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] Logical unit does not" \
|
||||
" have LBPWS10. Skipping test"); \
|
||||
CU_PASS("[SKIPPED] Logical unit does not have LBPWS10." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
#define CHECK_FOR_LBPWS10 \
|
||||
do { \
|
||||
if (inq_lbp->lbpws10 == 0) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] Logical unit does not" \
|
||||
" have LBPWS10. Skipping test"); \
|
||||
CU_PASS("[SKIPPED] Logical unit does not have LBPWS10." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define CHECK_FOR_LBPWS \
|
||||
do { \
|
||||
if (inq_lbp->lbpws == 0) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] Logical unit does not" \
|
||||
" have LBPWS. Skipping test"); \
|
||||
CU_PASS("[SKIPPED] Logical unit does not have LBPWS." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
#define CHECK_FOR_LBPWS \
|
||||
do { \
|
||||
if (inq_lbp->lbpws == 0) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] Logical unit does not" \
|
||||
" have LBPWS. Skipping test"); \
|
||||
CU_PASS("[SKIPPED] Logical unit does not have LBPWS." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define CHECK_FOR_LBPU \
|
||||
do { \
|
||||
if (inq_lbp->lbpu == 0) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] Logical unit does not" \
|
||||
" have LBPU. Skipping test"); \
|
||||
CU_PASS("[SKIPPED] Logical unit does not have LBPU." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
#define CHECK_FOR_LBPU \
|
||||
do { \
|
||||
if (inq_lbp->lbpu == 0) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] Logical unit does not" \
|
||||
" have LBPU. Skipping test"); \
|
||||
CU_PASS("[SKIPPED] Logical unit does not have LBPU." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define CHECK_FOR_LBPPB_GT_1 \
|
||||
do { \
|
||||
if (lbppb < 2) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] LBPPB < 2. Skipping test"); \
|
||||
CU_PASS("[SKIPPED] LBPPB < 2. Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
#define CHECK_FOR_LBPPB_GT_1 \
|
||||
do { \
|
||||
if (lbppb < 2) { \
|
||||
logging(LOG_NORMAL, "[SKIPPED] LBPPB < 2. Skipping test"); \
|
||||
CU_PASS("[SKIPPED] LBPPB < 2. Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define CHECK_FOR_SBC \
|
||||
do { \
|
||||
if (inq->device_type != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {\
|
||||
logging(LOG_NORMAL, "[SKIPPED] Not SBC device." \
|
||||
" Skipping test"); \
|
||||
CU_PASS("[SKIPPED] Not SBC device." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
#define CHECK_FOR_SBC \
|
||||
do { \
|
||||
if (inq->device_type != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {\
|
||||
logging(LOG_NORMAL, "[SKIPPED] Not SBC device." \
|
||||
" Skipping test"); \
|
||||
CU_PASS("[SKIPPED] Not SBC device." \
|
||||
" Skipping test"); \
|
||||
return; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define COMPAREANDWRITE(...) \
|
||||
@@ -704,23 +704,23 @@ extern int sbc3_support;
|
||||
extern int maximum_transfer_length;
|
||||
|
||||
struct scsi_device {
|
||||
char *error_str;
|
||||
char *error_str;
|
||||
|
||||
struct iscsi_context *iscsi_ctx;
|
||||
int iscsi_lun;
|
||||
char *iscsi_url;
|
||||
struct iscsi_context *iscsi_ctx;
|
||||
int iscsi_lun;
|
||||
char *iscsi_url;
|
||||
|
||||
char *sgio_dev;
|
||||
int sgio_fd;
|
||||
char *sgio_dev;
|
||||
int sgio_fd;
|
||||
};
|
||||
extern struct scsi_device *sd;
|
||||
|
||||
struct iscsi_context *iscsi_context_login(const char *initiatorname, const char *url, int *lun);
|
||||
|
||||
struct iscsi_async_state {
|
||||
struct scsi_task *task;
|
||||
int status;
|
||||
int finished;
|
||||
struct scsi_task *task;
|
||||
int status;
|
||||
int finished;
|
||||
};
|
||||
void wait_until_test_finished(struct iscsi_context *iscsi, struct iscsi_async_state *test_state);
|
||||
|
||||
@@ -735,32 +735,32 @@ struct scsi_command_descriptor *get_command_descriptor(int opcode, int sa);
|
||||
|
||||
static inline long rand_key(void)
|
||||
{
|
||||
static int seed = 0;
|
||||
static int seed = 0;
|
||||
|
||||
if (!seed) {
|
||||
struct timeval tv;
|
||||
pid_t p;
|
||||
unsigned int s;
|
||||
if (!seed) {
|
||||
struct timeval tv;
|
||||
pid_t p;
|
||||
unsigned int s;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
p = getpid();
|
||||
s = p ^ tv.tv_sec ^ tv.tv_usec;
|
||||
srandom(s);
|
||||
}
|
||||
seed = 1;
|
||||
return random();
|
||||
gettimeofday(&tv, NULL);
|
||||
p = getpid();
|
||||
s = p ^ tv.tv_sec ^ tv.tv_usec;
|
||||
srandom(s);
|
||||
}
|
||||
seed = 1;
|
||||
return random();
|
||||
}
|
||||
|
||||
static inline int pr_type_is_all_registrants(
|
||||
enum scsi_persistent_out_type pr_type)
|
||||
enum scsi_persistent_out_type pr_type)
|
||||
{
|
||||
switch (pr_type) {
|
||||
case SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_ALL_REGISTRANTS:
|
||||
case SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_ALL_REGISTRANTS:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
switch (pr_type) {
|
||||
case SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_ALL_REGISTRANTS:
|
||||
case SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_ALL_REGISTRANTS:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int all_zeroes(const unsigned char *buf, unsigned size);
|
||||
@@ -783,13 +783,13 @@ int prout_release(struct scsi_device *sdev,
|
||||
unsigned long long key, enum scsi_persistent_out_type pr_type);
|
||||
int prout_clear(struct scsi_device *sdev, unsigned long long key);
|
||||
int prout_preempt(struct scsi_device *sdev,
|
||||
unsigned long long sark, unsigned long long rk,
|
||||
enum scsi_persistent_out_type pr_type);
|
||||
unsigned long long sark, unsigned long long rk,
|
||||
enum scsi_persistent_out_type pr_type);
|
||||
int prin_verify_not_reserved(struct scsi_device *sdev);
|
||||
int prin_verify_reserved_as(struct scsi_device *sdev,
|
||||
unsigned long long key, enum scsi_persistent_out_type pr_type);
|
||||
int prin_report_caps(struct scsi_device *sdev, struct scsi_task **tp,
|
||||
struct scsi_persistent_reserve_in_report_capabilities **_rcaps);
|
||||
struct scsi_persistent_reserve_in_report_capabilities **_rcaps);
|
||||
int verify_read_works(struct scsi_device *sdev, unsigned char *buf);
|
||||
int verify_write_works(struct scsi_device *sdev, unsigned char *buf);
|
||||
int verify_read_fails(struct scsi_device *sdev, unsigned char *buf);
|
||||
@@ -844,8 +844,8 @@ int populate_seg_desc_hdr(unsigned char *hdr, enum ec_descr_type_code desc_type,
|
||||
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_task **task, 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);
|
||||
enum scsi_copy_results_sa sa, int list_id,
|
||||
void **datap, int status, enum scsi_sense_key key,
|
||||
int *ascq, int num_ascq);
|
||||
int test_iscsi_tur_until_good(struct scsi_device *iscsi_sd, int *num_uas);
|
||||
#endif /* _ISCSI_SUPPORT_H_ */
|
||||
#endif /* _ISCSI_SUPPORT_H_ */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,8 +17,8 @@
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ISCSI_TEST_CU_H_
|
||||
#define _ISCSI_TEST_CU_H_
|
||||
#ifndef _ISCSI_TEST_CU_H_
|
||||
#define _ISCSI_TEST_CU_H_
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
@@ -308,4 +308,4 @@ void test_multipathio_simple(void);
|
||||
void test_multipathio_reset(void);
|
||||
void test_multipathio_compareandwrite(void);
|
||||
|
||||
#endif /* _ISCSI_TEST_CU_H_ */
|
||||
#endif /* _ISCSI_TEST_CU_H_ */
|
||||
|
||||
@@ -29,90 +29,90 @@
|
||||
void
|
||||
test_compareandwrite_dpofua(void)
|
||||
{
|
||||
int ret, dpofua, usage_data_dpofua;
|
||||
struct scsi_task *ms_task = NULL;
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_task *rso_task = NULL;
|
||||
struct scsi_report_supported_op_codes_one_command *rsoc;
|
||||
int ret, dpofua, usage_data_dpofua;
|
||||
struct scsi_task *ms_task = NULL;
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_task *rso_task = NULL;
|
||||
struct scsi_report_supported_op_codes_one_command *rsoc;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test COMPAREANDWRITE DPO/FUA flags");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test COMPAREANDWRITE DPO/FUA flags");
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_DATALOSS;
|
||||
|
||||
logging(LOG_VERBOSE, "Read the DPOFUA flag from mode sense data");
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
logging(LOG_VERBOSE, "Read the DPOFUA flag from mode sense data");
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode sense returned status GOOD");
|
||||
ms = scsi_datain_unmarshall(ms_task);
|
||||
dpofua = ms && (ms->device_specific_parameter & 0x10);
|
||||
scsi_free_scsi_task(ms_task);
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode sense returned status GOOD");
|
||||
ms = scsi_datain_unmarshall(ms_task);
|
||||
dpofua = ms && (ms->device_specific_parameter & 0x10);
|
||||
scsi_free_scsi_task(ms_task);
|
||||
|
||||
logging(LOG_VERBOSE, "Read the first block");
|
||||
ret = read10(sd, NULL, 0, block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret == 0)
|
||||
memcpy(scratch + block_size, scratch, block_size);
|
||||
else
|
||||
memset(scratch, 0xa6, 2 * block_size);
|
||||
logging(LOG_VERBOSE, "Read the first block");
|
||||
ret = read10(sd, NULL, 0, block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret == 0)
|
||||
memcpy(scratch + block_size, scratch, block_size);
|
||||
else
|
||||
memset(scratch, 0xa6, 2 * block_size);
|
||||
|
||||
if (dpofua) {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is set. Device should allow "
|
||||
"DPO/FUA flags in CDBs");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is clear. Device should fail "
|
||||
"CDBs with DPO/FUA set");
|
||||
}
|
||||
if (dpofua) {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is set. Device should allow "
|
||||
"DPO/FUA flags in CDBs");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is clear. Device should fail "
|
||||
"CDBs with DPO/FUA set");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test COMPAREANDWRITE with DPO==1");
|
||||
if (dpofua) {
|
||||
COMPAREANDWRITE(sd, 0, scratch, 2 * block_size,
|
||||
logging(LOG_VERBOSE, "Test COMPAREANDWRITE with DPO==1");
|
||||
if (dpofua) {
|
||||
COMPAREANDWRITE(sd, 0, scratch, 2 * block_size,
|
||||
block_size, 0, 1, 0, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
} else {
|
||||
COMPAREANDWRITE(sd, 0, scratch, 2 * block_size,
|
||||
} else {
|
||||
COMPAREANDWRITE(sd, 0, scratch, 2 * block_size,
|
||||
block_size, 0, 1, 0, 0,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test COMPAREANDWRITE with FUA==1");
|
||||
if (dpofua) {
|
||||
COMPAREANDWRITE(sd, 0, scratch, 2 * block_size,
|
||||
logging(LOG_VERBOSE, "Test COMPAREANDWRITE with FUA==1");
|
||||
if (dpofua) {
|
||||
COMPAREANDWRITE(sd, 0, scratch, 2 * block_size,
|
||||
block_size, 0, 0, 1, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
} else {
|
||||
COMPAREANDWRITE(sd, 0, scratch, 2 * block_size,
|
||||
} else {
|
||||
COMPAREANDWRITE(sd, 0, scratch, 2 * block_size,
|
||||
block_size, 0, 0, 1, 0,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test COMPAREANDWRITE with DPO==1 FUA==1");
|
||||
if (dpofua) {
|
||||
COMPAREANDWRITE(sd, 0, scratch, 2 * block_size,
|
||||
logging(LOG_VERBOSE, "Test COMPAREANDWRITE with DPO==1 FUA==1");
|
||||
if (dpofua) {
|
||||
COMPAREANDWRITE(sd, 0, scratch, 2 * block_size,
|
||||
block_size, 0, 1, 1, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
} else {
|
||||
COMPAREANDWRITE(sd, 0, scratch, 2 * block_size,
|
||||
} else {
|
||||
COMPAREANDWRITE(sd, 0, scratch, 2 * block_size,
|
||||
block_size, 0, 1, 1, 0,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Try fetching REPORT_SUPPORTED_OPCODES "
|
||||
"for COMPAREANDWRITE");
|
||||
REPORT_SUPPORTED_OPCODES(sd, &rso_task,
|
||||
logging(LOG_VERBOSE, "Try fetching REPORT_SUPPORTED_OPCODES "
|
||||
"for COMPAREANDWRITE");
|
||||
REPORT_SUPPORTED_OPCODES(sd, &rso_task,
|
||||
0, SCSI_REPORT_SUPPORTING_OPCODE,
|
||||
SCSI_OPCODE_COMPARE_AND_WRITE,
|
||||
0,
|
||||
65535,
|
||||
EXPECT_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc);
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc);
|
||||
|
||||
usage_data_dpofua = rsoc->cdb_usage_data[1] & 0x18;
|
||||
if (dpofua) {
|
||||
@@ -133,5 +133,5 @@ test_compareandwrite_dpofua(void)
|
||||
}
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(rso_task);
|
||||
scsi_free_scsi_task(rso_task);
|
||||
}
|
||||
|
||||
@@ -31,125 +31,125 @@
|
||||
void
|
||||
test_compareandwrite_miscompare(void)
|
||||
{
|
||||
int i;
|
||||
unsigned j;
|
||||
int maxbl;
|
||||
int i;
|
||||
unsigned j;
|
||||
int maxbl;
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
if (inq_bl && inq_bl->max_cmp) {
|
||||
maxbl = inq_bl->max_cmp;
|
||||
} else {
|
||||
/* Assume we are not limited */
|
||||
maxbl = 256;
|
||||
}
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test COMPARE_AND_WRITE of 1-256 blocks at the "
|
||||
"start of the LUN. One Byte miscompare in the final block.");
|
||||
for (i = 1; i < 256; i++) {
|
||||
logging(LOG_VERBOSE, "Write %d blocks of 'A' at LBA:0", i);
|
||||
memset(scratch, 'A', 2 * i * block_size);
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
WRITE16(sd, 0, i * block_size,
|
||||
if (inq_bl && inq_bl->max_cmp) {
|
||||
maxbl = inq_bl->max_cmp;
|
||||
} else {
|
||||
/* Assume we are not limited */
|
||||
maxbl = 256;
|
||||
}
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test COMPARE_AND_WRITE of 1-256 blocks at the "
|
||||
"start of the LUN. One Byte miscompare in the final block.");
|
||||
for (i = 1; i < 256; i++) {
|
||||
logging(LOG_VERBOSE, "Write %d blocks of 'A' at LBA:0", i);
|
||||
memset(scratch, 'A', 2 * i * block_size);
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
WRITE16(sd, 0, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Change byte 27 from the end to 'C' so that it does not match.");
|
||||
scratch[i * block_size - 27] = 'C';
|
||||
|
||||
logging(LOG_VERBOSE, "Change byte 27 from the end to 'C' so that it does not match.");
|
||||
scratch[i * block_size - 27] = 'C';
|
||||
|
||||
if (i > maxbl) {
|
||||
logging(LOG_VERBOSE, "Number of blocks %d is greater than "
|
||||
"BlockLimits.MaximumCompareAndWriteLength(%d). "
|
||||
"Command should fail with INVALID_FIELD_IN_CDB",
|
||||
i, maxbl);
|
||||
COMPAREANDWRITE(sd, 0,
|
||||
if (i > maxbl) {
|
||||
logging(LOG_VERBOSE, "Number of blocks %d is greater than "
|
||||
"BlockLimits.MaximumCompareAndWriteLength(%d). "
|
||||
"Command should fail with INVALID_FIELD_IN_CDB",
|
||||
i, maxbl);
|
||||
COMPAREANDWRITE(sd, 0,
|
||||
scratch, 2 * i * block_size,
|
||||
block_size, 0, 0, 0, 0,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(scratch + i * block_size, 'B', i * block_size);
|
||||
memset(scratch + i * block_size, 'B', i * block_size);
|
||||
|
||||
logging(LOG_VERBOSE, "Overwrite %d blocks with 'B' "
|
||||
"at LBA:0 (if they all contain 'A')", i);
|
||||
COMPAREANDWRITE(sd, 0,
|
||||
logging(LOG_VERBOSE, "Overwrite %d blocks with 'B' "
|
||||
"at LBA:0 (if they all contain 'A')", i);
|
||||
COMPAREANDWRITE(sd, 0,
|
||||
scratch, 2 * i * block_size, block_size,
|
||||
0, 0, 0, 0,
|
||||
EXPECT_MISCOMPARE);
|
||||
|
||||
logging(LOG_VERBOSE, "Read %d blocks at LBA:0 and verify "
|
||||
"they are still unchanged as 'A'", i);
|
||||
READ16(sd, NULL, 0, i * block_size,
|
||||
logging(LOG_VERBOSE, "Read %d blocks at LBA:0 and verify "
|
||||
"they are still unchanged as 'A'", i);
|
||||
READ16(sd, NULL, 0, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
for (j = 0; j < i * block_size; j++) {
|
||||
if (scratch[j] != 'A') {
|
||||
logging(LOG_VERBOSE, "[FAILED] Data changed "
|
||||
"eventhough there was a miscompare");
|
||||
CU_FAIL("Block was written to");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (j = 0; j < i * block_size; j++) {
|
||||
if (scratch[j] != 'A') {
|
||||
logging(LOG_VERBOSE, "[FAILED] Data changed "
|
||||
"eventhough there was a miscompare");
|
||||
CU_FAIL("Block was written to");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Test COMPARE_AND_WRITE of 1-256 blocks at the "
|
||||
"end of the LUN");
|
||||
for (i = 1; i < 256; i++) {
|
||||
logging(LOG_VERBOSE, "Write %d blocks of 'A' at LBA:%" PRIu64,
|
||||
i, num_blocks - i);
|
||||
memset(scratch, 'A', 2 * i * block_size);
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
WRITE16(sd, num_blocks - i, i * block_size,
|
||||
logging(LOG_VERBOSE, "Test COMPARE_AND_WRITE of 1-256 blocks at the "
|
||||
"end of the LUN");
|
||||
for (i = 1; i < 256; i++) {
|
||||
logging(LOG_VERBOSE, "Write %d blocks of 'A' at LBA:%" PRIu64,
|
||||
i, num_blocks - i);
|
||||
memset(scratch, 'A', 2 * i * block_size);
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
WRITE16(sd, num_blocks - i, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Change byte 27 from the end to 'C' so that it does not match.");
|
||||
scratch[i * block_size - 27] = 'C';
|
||||
logging(LOG_VERBOSE, "Change byte 27 from the end to 'C' so that it does not match.");
|
||||
scratch[i * block_size - 27] = 'C';
|
||||
|
||||
|
||||
if (i > maxbl) {
|
||||
logging(LOG_VERBOSE, "Number of blocks %d is greater than "
|
||||
"BlockLimits.MaximumCompareAndWriteLength(%d). "
|
||||
"Command should fail with INVALID_FIELD_IN_CDB",
|
||||
i, maxbl);
|
||||
COMPAREANDWRITE(sd, 0,
|
||||
if (i > maxbl) {
|
||||
logging(LOG_VERBOSE, "Number of blocks %d is greater than "
|
||||
"BlockLimits.MaximumCompareAndWriteLength(%d). "
|
||||
"Command should fail with INVALID_FIELD_IN_CDB",
|
||||
i, maxbl);
|
||||
COMPAREANDWRITE(sd, 0,
|
||||
scratch, 2 * i * block_size,
|
||||
block_size, 0, 0, 0, 0,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
continue;
|
||||
}
|
||||
memset(scratch + i * block_size, 'B', i * block_size);
|
||||
continue;
|
||||
}
|
||||
memset(scratch + i * block_size, 'B', i * block_size);
|
||||
|
||||
logging(LOG_VERBOSE, "Overwrite %d blocks with 'B' "
|
||||
"at LBA:%" PRIu64 " (if they all contain 'A')",
|
||||
i, num_blocks - i);
|
||||
COMPAREANDWRITE(sd, num_blocks - i,
|
||||
logging(LOG_VERBOSE, "Overwrite %d blocks with 'B' "
|
||||
"at LBA:%" PRIu64 " (if they all contain 'A')",
|
||||
i, num_blocks - i);
|
||||
COMPAREANDWRITE(sd, num_blocks - i,
|
||||
scratch, 2 * i * block_size, block_size,
|
||||
0, 0, 0, 0,
|
||||
EXPECT_MISCOMPARE);
|
||||
|
||||
logging(LOG_VERBOSE, "Read %d blocks at LBA:%" PRIu64
|
||||
"they are still unchanged as 'A'",
|
||||
i, num_blocks - i);
|
||||
READ16(sd, NULL, num_blocks - i, i * block_size,
|
||||
logging(LOG_VERBOSE, "Read %d blocks at LBA:%" PRIu64
|
||||
"they are still unchanged as 'A'",
|
||||
i, num_blocks - i);
|
||||
READ16(sd, NULL, num_blocks - i, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
for (j = 0; j < i * block_size; j++) {
|
||||
if (scratch[j] != 'A') {
|
||||
logging(LOG_VERBOSE, "[FAILED] Data changed "
|
||||
"eventhough there was a miscompare");
|
||||
CU_FAIL("Block was written to");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (j = 0; j < i * block_size; j++) {
|
||||
if (scratch[j] != 'A') {
|
||||
logging(LOG_VERBOSE, "[FAILED] Data changed "
|
||||
"eventhough there was a miscompare");
|
||||
CU_FAIL("Block was written to");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,121 +31,121 @@
|
||||
void
|
||||
test_compareandwrite_simple(void)
|
||||
{
|
||||
int i;
|
||||
unsigned j;
|
||||
int maxbl;
|
||||
int i;
|
||||
unsigned j;
|
||||
int maxbl;
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
if (inq_bl && inq_bl->max_cmp) {
|
||||
maxbl = inq_bl->max_cmp;
|
||||
} else {
|
||||
/* Assume we are not limited */
|
||||
maxbl = 256;
|
||||
}
|
||||
if (inq_bl && inq_bl->max_cmp) {
|
||||
maxbl = inq_bl->max_cmp;
|
||||
} else {
|
||||
/* Assume we are not limited */
|
||||
maxbl = 256;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test COMPARE_AND_WRITE of 1-256 blocks at the "
|
||||
"start of the LUN");
|
||||
for (i = 1; i < 256; i++) {
|
||||
logging(LOG_VERBOSE, "Write %d blocks of 'A' at LBA:0", i);
|
||||
memset(scratch, 'A', 2 * i * block_size);
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
WRITE16(sd, 0, i * block_size,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test COMPARE_AND_WRITE of 1-256 blocks at the "
|
||||
"start of the LUN");
|
||||
for (i = 1; i < 256; i++) {
|
||||
logging(LOG_VERBOSE, "Write %d blocks of 'A' at LBA:0", i);
|
||||
memset(scratch, 'A', 2 * i * block_size);
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
WRITE16(sd, 0, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
if (i > maxbl) {
|
||||
logging(LOG_VERBOSE, "Number of blocks %d is greater than "
|
||||
"BlockLimits.MaximumCompareAndWriteLength(%d). "
|
||||
"Command should fail with INVALID_FIELD_IN_CDB",
|
||||
i, maxbl);
|
||||
COMPAREANDWRITE(sd, 0,
|
||||
if (i > maxbl) {
|
||||
logging(LOG_VERBOSE, "Number of blocks %d is greater than "
|
||||
"BlockLimits.MaximumCompareAndWriteLength(%d). "
|
||||
"Command should fail with INVALID_FIELD_IN_CDB",
|
||||
i, maxbl);
|
||||
COMPAREANDWRITE(sd, 0,
|
||||
scratch, 2 * i * block_size,
|
||||
block_size, 0, 0, 0, 0,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(scratch + i * block_size, 'B', i * block_size);
|
||||
memset(scratch + i * block_size, 'B', i * block_size);
|
||||
|
||||
logging(LOG_VERBOSE, "Overwrite %d blocks with 'B' "
|
||||
"at LBA:0 (if they all contain 'A')", i);
|
||||
COMPAREANDWRITE(sd, 0,
|
||||
logging(LOG_VERBOSE, "Overwrite %d blocks with 'B' "
|
||||
"at LBA:0 (if they all contain 'A')", i);
|
||||
COMPAREANDWRITE(sd, 0,
|
||||
scratch, 2 * i * block_size, block_size,
|
||||
0, 0, 0, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Read %d blocks at LBA:0 and verify "
|
||||
"they are all 'B'", i);
|
||||
READ16(sd, NULL, 0, i * block_size,
|
||||
logging(LOG_VERBOSE, "Read %d blocks at LBA:0 and verify "
|
||||
"they are all 'B'", i);
|
||||
READ16(sd, NULL, 0, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
for (j = 0; j < i * block_size; j++) {
|
||||
if (scratch[j] != 'B') {
|
||||
logging(LOG_VERBOSE, "[FAILED] Data did not "
|
||||
"read back as 'B' (scratch[%d] = %#02x)",
|
||||
j, scratch[j]);
|
||||
CU_FAIL("Block was not written correctly");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (j = 0; j < i * block_size; j++) {
|
||||
if (scratch[j] != 'B') {
|
||||
logging(LOG_VERBOSE, "[FAILED] Data did not "
|
||||
"read back as 'B' (scratch[%d] = %#02x)",
|
||||
j, scratch[j]);
|
||||
CU_FAIL("Block was not written correctly");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Test COMPARE_AND_WRITE of 1-256 blocks at the "
|
||||
"end of the LUN");
|
||||
for (i = 1; i < 256; i++) {
|
||||
logging(LOG_VERBOSE, "Write %d blocks of 'A' at LBA:%" PRIu64,
|
||||
i, num_blocks - i);
|
||||
memset(scratch, 'A', 2 * i * block_size);
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
WRITE16(sd, num_blocks - i, i * block_size,
|
||||
logging(LOG_VERBOSE, "Test COMPARE_AND_WRITE of 1-256 blocks at the "
|
||||
"end of the LUN");
|
||||
for (i = 1; i < 256; i++) {
|
||||
logging(LOG_VERBOSE, "Write %d blocks of 'A' at LBA:%" PRIu64,
|
||||
i, num_blocks - i);
|
||||
memset(scratch, 'A', 2 * i * block_size);
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
WRITE16(sd, num_blocks - i, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
if (i > maxbl) {
|
||||
logging(LOG_VERBOSE, "Number of blocks %d is greater than "
|
||||
"BlockLimits.MaximumCompareAndWriteLength(%d). "
|
||||
"Command should fail with INVALID_FIELD_IN_CDB",
|
||||
i, maxbl);
|
||||
COMPAREANDWRITE(sd, 0,
|
||||
if (i > maxbl) {
|
||||
logging(LOG_VERBOSE, "Number of blocks %d is greater than "
|
||||
"BlockLimits.MaximumCompareAndWriteLength(%d). "
|
||||
"Command should fail with INVALID_FIELD_IN_CDB",
|
||||
i, maxbl);
|
||||
COMPAREANDWRITE(sd, 0,
|
||||
scratch, 2 * i * block_size,
|
||||
block_size, 0, 0, 0, 0,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
continue;
|
||||
}
|
||||
memset(scratch + i * block_size, 'B', i * block_size);
|
||||
continue;
|
||||
}
|
||||
memset(scratch + i * block_size, 'B', i * block_size);
|
||||
|
||||
logging(LOG_VERBOSE, "Overwrite %d blocks with 'B' "
|
||||
"at LBA:%" PRIu64 " (if they all contain 'A')",
|
||||
i, num_blocks - i);
|
||||
COMPAREANDWRITE(sd, num_blocks - i,
|
||||
logging(LOG_VERBOSE, "Overwrite %d blocks with 'B' "
|
||||
"at LBA:%" PRIu64 " (if they all contain 'A')",
|
||||
i, num_blocks - i);
|
||||
COMPAREANDWRITE(sd, num_blocks - i,
|
||||
scratch, 2 * i * block_size, block_size,
|
||||
0, 0, 0, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Read %d blocks at LBA:%" PRIu64
|
||||
" and verify they are all 'B'",
|
||||
i, num_blocks - i);
|
||||
READ16(sd, NULL, num_blocks - i, i * block_size,
|
||||
logging(LOG_VERBOSE, "Read %d blocks at LBA:%" PRIu64
|
||||
" and verify they are all 'B'",
|
||||
i, num_blocks - i);
|
||||
READ16(sd, NULL, num_blocks - i, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
for (j = 0; j < i * block_size; j++) {
|
||||
if (scratch[j] != 'B') {
|
||||
logging(LOG_VERBOSE, "[FAILED] Data did not "
|
||||
"read back as 'B' (scratch[%d] = %#02x)",
|
||||
j, scratch[j]);
|
||||
CU_FAIL("Block was not written correctly");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (j = 0; j < i * block_size; j++) {
|
||||
if (scratch[j] != 'B') {
|
||||
logging(LOG_VERBOSE, "[FAILED] Data did not "
|
||||
"read back as 'B' (scratch[%d] = %#02x)",
|
||||
j, scratch[j]);
|
||||
CU_FAIL("Block was not written correctly");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,88 +28,88 @@
|
||||
#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 num_seg_desc, int *tgt_desc_len, int *seg_desc_len)
|
||||
{
|
||||
int i;
|
||||
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;
|
||||
/* 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;
|
||||
/* 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;
|
||||
return offset;
|
||||
}
|
||||
|
||||
void
|
||||
test_extendedcopy_descr_limits(void)
|
||||
{
|
||||
struct scsi_task *edl_task;
|
||||
struct iscsi_data data;
|
||||
unsigned char *xcopybuf;
|
||||
struct scsi_copy_results_op_params *opp = NULL;
|
||||
int tgt_desc_len = 0, seg_desc_len = 0;
|
||||
unsigned int alloc_len;
|
||||
struct scsi_task *edl_task;
|
||||
struct iscsi_data data;
|
||||
unsigned char *xcopybuf;
|
||||
struct scsi_copy_results_op_params *opp = NULL;
|
||||
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");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test EXTENDED COPY descriptor limits");
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_DATALOSS;
|
||||
|
||||
logging(LOG_VERBOSE, "Issue RECEIVE COPY RESULTS (OPERATING PARAMS)");
|
||||
RECEIVE_COPY_RESULTS(&edl_task, sd, SCSI_COPY_RESULTS_OP_PARAMS, 0,
|
||||
logging(LOG_VERBOSE, "Issue RECEIVE COPY RESULTS (OPERATING PARAMS)");
|
||||
RECEIVE_COPY_RESULTS(&edl_task, sd, SCSI_COPY_RESULTS_OP_PARAMS, 0,
|
||||
(void **)&opp, EXPECT_STATUS_GOOD);
|
||||
|
||||
/* 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;
|
||||
memset(xcopybuf, 0, alloc_len);
|
||||
/* 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;
|
||||
memset(xcopybuf, 0, alloc_len);
|
||||
|
||||
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);
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_TOO_MANY_DESCR);
|
||||
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);
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_TOO_MANY_DESCR);
|
||||
|
||||
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);
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_TOO_MANY_DESCR);
|
||||
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);
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_TOO_MANY_DESCR);
|
||||
|
||||
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);
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_PARAM_LIST_LEN_ERR);
|
||||
}
|
||||
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);
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_PARAM_LIST_LEN_ERR);
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(edl_task);
|
||||
scsi_free_scsi_task(edl_task);
|
||||
}
|
||||
|
||||
@@ -28,60 +28,60 @@
|
||||
#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 *tgt_desc_len, int *seg_desc_len)
|
||||
{
|
||||
int offset = XCOPY_DESC_OFFSET;
|
||||
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;
|
||||
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;
|
||||
return offset;
|
||||
}
|
||||
|
||||
void
|
||||
test_extendedcopy_descr_type(void)
|
||||
{
|
||||
int tgt_desc_len = 0, seg_desc_len = 0, alloc_len;
|
||||
struct iscsi_data data;
|
||||
unsigned char *xcopybuf;
|
||||
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");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE,
|
||||
"Test EXTENDED COPY unsupported descriptor types");
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
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;
|
||||
memset(xcopybuf, 0, alloc_len);
|
||||
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;
|
||||
memset(xcopybuf, 0, alloc_len);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_UNSUPP_DESCR_CODE);
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_UNSUPP_DESCR_CODE);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_UNSUPP_DESCR_CODE);
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_UNSUPP_DESCR_CODE);
|
||||
}
|
||||
|
||||
@@ -30,47 +30,47 @@
|
||||
void
|
||||
test_extendedcopy_param(void)
|
||||
{
|
||||
int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET;
|
||||
struct iscsi_data data;
|
||||
unsigned char *xcopybuf;
|
||||
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");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test EXTENDED COPY parameter list length");
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
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;
|
||||
memset(xcopybuf, 0, data.size);
|
||||
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;
|
||||
memset(xcopybuf, 0, data.size);
|
||||
|
||||
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_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;
|
||||
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);
|
||||
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;
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_PARAM_LIST_LEN_ERR);
|
||||
logging(LOG_VERBOSE,
|
||||
"Test parameter list length truncating target descriptor");
|
||||
data.size = XCOPY_DESC_OFFSET +
|
||||
get_desc_len(IDENT_DESCR_TGT_DESCR) - 1;
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_PARAM_LIST_LEN_ERR);
|
||||
|
||||
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;
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_PARAM_LIST_LEN_ERR);
|
||||
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;
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_PARAM_LIST_LEN_ERR);
|
||||
|
||||
logging(LOG_VERBOSE, "Test parameter list length = 0");
|
||||
data.size = 0;
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Test parameter list length = 0");
|
||||
data.size = 0;
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_STATUS_GOOD);
|
||||
}
|
||||
|
||||
@@ -30,55 +30,55 @@
|
||||
void
|
||||
test_extendedcopy_simple(void)
|
||||
{
|
||||
int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET;
|
||||
struct iscsi_data data;
|
||||
unsigned char *xcopybuf;
|
||||
unsigned char *buf1 = malloc(2048*block_size);
|
||||
unsigned char *buf2 = malloc(2048*block_size);
|
||||
int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET;
|
||||
struct iscsi_data data;
|
||||
unsigned char *xcopybuf;
|
||||
unsigned char *buf1 = malloc(2048*block_size);
|
||||
unsigned char *buf2 = malloc(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");
|
||||
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;
|
||||
CHECK_FOR_DATALOSS;
|
||||
|
||||
logging(LOG_VERBOSE, "Write 2048 blocks of 'A' at LBA:0");
|
||||
memset(buf1, 'A', 2048*block_size);
|
||||
WRITE16(sd, 0, 2048*block_size, block_size, 0, 0, 0, 0, 0,
|
||||
logging(LOG_VERBOSE, "Write 2048 blocks of 'A' at LBA:0");
|
||||
memset(buf1, 'A', 2048*block_size);
|
||||
WRITE16(sd, 0, 2048*block_size, block_size, 0, 0, 0, 0, 0,
|
||||
buf1, EXPECT_STATUS_GOOD);
|
||||
|
||||
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;
|
||||
memset(xcopybuf, 0, data.size);
|
||||
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;
|
||||
memset(xcopybuf, 0, data.size);
|
||||
|
||||
/* 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;
|
||||
/* 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;
|
||||
/* 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);
|
||||
/* Initialize the parameter list header */
|
||||
populate_param_header(xcopybuf, 1, 0, LIST_ID_USAGE_DISCARD, 0,
|
||||
tgt_desc_len, seg_desc_len, 0);
|
||||
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_STATUS_GOOD);
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Read 2048 blocks from end of the LUN");
|
||||
READ16(sd, NULL, num_blocks - 2048, 2048*block_size,
|
||||
logging(LOG_VERBOSE, "Read 2048 blocks from end of the LUN");
|
||||
READ16(sd, NULL, num_blocks - 2048, 2048*block_size,
|
||||
block_size, 0, 0, 0, 0, 0, buf2,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
if (memcmp(buf1, buf2, 2048)) {
|
||||
CU_FAIL("Blocks were not copied correctly");
|
||||
if (memcmp(buf1, buf2, 2048)) {
|
||||
CU_FAIL("Blocks were not copied correctly");
|
||||
}
|
||||
|
||||
free(buf1);
|
||||
free(buf2);
|
||||
free(buf1);
|
||||
free(buf2);
|
||||
}
|
||||
|
||||
@@ -30,48 +30,48 @@
|
||||
void
|
||||
test_extendedcopy_validate_seg_descr(void)
|
||||
{
|
||||
int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET;
|
||||
struct iscsi_data data;
|
||||
unsigned char *xcopybuf;
|
||||
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");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test EXTENDED COPY segment descriptor fields");
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
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;
|
||||
memset(xcopybuf, 0, data.size);
|
||||
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;
|
||||
memset(xcopybuf, 0, data.size);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_COPY_ABORTED);
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_COPY_ABORTED);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_COPY_ABORTED);
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_COPY_ABORTED);
|
||||
}
|
||||
|
||||
@@ -30,47 +30,47 @@
|
||||
void
|
||||
test_extendedcopy_validate_tgt_descr(void)
|
||||
{
|
||||
int tgt_desc_len = 0, seg_desc_len = 0, offset = XCOPY_DESC_OFFSET;
|
||||
struct iscsi_data data;
|
||||
unsigned char *xcopybuf;
|
||||
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");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test EXTENDED COPY target descriptor fields");
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
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;
|
||||
memset(xcopybuf, 0, data.size);
|
||||
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;
|
||||
memset(xcopybuf, 0, data.size);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_INVALID_FIELD_IN_CDB);
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_INVALID_FIELD_IN_CDB);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_COPY_ABORTED);
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_COPY_ABORTED);
|
||||
}
|
||||
|
||||
@@ -29,17 +29,17 @@
|
||||
void
|
||||
test_get_lba_status_beyond_eol(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test GETLBASTATUS one block beyond the end of the LUN");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test GETLBASTATUS one block beyond the end of the LUN");
|
||||
|
||||
GETLBASTATUS(sd, NULL, num_blocks + 1, 24,
|
||||
GETLBASTATUS(sd, NULL, num_blocks + 1, 24,
|
||||
EXPECT_LBA_OOB);
|
||||
|
||||
logging(LOG_VERBOSE, "Test GETLBASTATUS at LBA 2^63");
|
||||
GETLBASTATUS(sd, NULL, 0x8000000000000000ULL, 24,
|
||||
logging(LOG_VERBOSE, "Test GETLBASTATUS at LBA 2^63");
|
||||
GETLBASTATUS(sd, NULL, 0x8000000000000000ULL, 24,
|
||||
EXPECT_LBA_OOB);
|
||||
|
||||
logging(LOG_VERBOSE, "Test GETLBASTATUS at LBA -1");
|
||||
GETLBASTATUS(sd, NULL, 0xffffffffffffffffULL, 24,
|
||||
logging(LOG_VERBOSE, "Test GETLBASTATUS at LBA -1");
|
||||
GETLBASTATUS(sd, NULL, 0xffffffffffffffffULL, 24,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
|
||||
@@ -29,18 +29,18 @@
|
||||
void
|
||||
test_get_lba_status_simple(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test GETLBASTATUS of 1-256 blocks at the start of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
GETLBASTATUS(sd, NULL, i, 24,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test GETLBASTATUS of 1-256 blocks at the start of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
GETLBASTATUS(sd, NULL, i, 24,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test GETLBASTATUS of 1-256 blocks at the end of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
GETLBASTATUS(sd, NULL, num_blocks - i, 24,
|
||||
logging(LOG_VERBOSE, "Test GETLBASTATUS of 1-256 blocks at the end of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
GETLBASTATUS(sd, NULL, num_blocks - i, 24,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,120 +29,120 @@
|
||||
void
|
||||
test_get_lba_status_unmap_single(void)
|
||||
{
|
||||
uint64_t i;
|
||||
struct unmap_list list[1];
|
||||
struct scsi_task *t = NULL;
|
||||
struct scsi_get_lba_status *lbas = NULL;
|
||||
struct scsi_lba_status_descriptor *lbasd = NULL;
|
||||
uint64_t i;
|
||||
struct unmap_list list[1];
|
||||
struct scsi_task *t = NULL;
|
||||
struct scsi_get_lba_status *lbas = NULL;
|
||||
struct scsi_lba_status_descriptor *lbasd = NULL;
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_THIN_PROVISIONING;
|
||||
CHECK_FOR_LBPU;
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_THIN_PROVISIONING;
|
||||
CHECK_FOR_LBPU;
|
||||
|
||||
memset(scratch, 'A', (256 + lbppb + 1) * block_size);
|
||||
memset(scratch, 'A', (256 + lbppb + 1) * block_size);
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test GETLBASTATUS for a single unmapped block "
|
||||
"at offset 0-255");
|
||||
logging(LOG_VERBOSE, "We have %d logical blocks per physical block",
|
||||
lbppb);
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test GETLBASTATUS for a single unmapped block "
|
||||
"at offset 0-255");
|
||||
logging(LOG_VERBOSE, "We have %d logical blocks per physical block",
|
||||
lbppb);
|
||||
|
||||
logging(LOG_VERBOSE, "Write the first %i blocks with a known "
|
||||
"pattern and thus map the blocks", 256 + lbppb);
|
||||
WRITE10(sd, 0, (256 + lbppb) * block_size,
|
||||
logging(LOG_VERBOSE, "Write the first %i blocks with a known "
|
||||
"pattern and thus map the blocks", 256 + lbppb);
|
||||
WRITE10(sd, 0, (256 + lbppb) * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
for (i = 0; i + lbppb <= 256; i += lbppb) {
|
||||
logging(LOG_VERBOSE, "Unmap a single physical block at LBA:%"
|
||||
PRIu64 " (number of logical blocks: %d)", i, lbppb);
|
||||
list[0].lba = i;
|
||||
list[0].num = lbppb;
|
||||
UNMAP(sd, 0, list, 1,
|
||||
for (i = 0; i + lbppb <= 256; i += lbppb) {
|
||||
logging(LOG_VERBOSE, "Unmap a single physical block at LBA:%"
|
||||
PRIu64 " (number of logical blocks: %d)", i, lbppb);
|
||||
list[0].lba = i;
|
||||
list[0].num = lbppb;
|
||||
UNMAP(sd, 0, list, 1,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Read the status of the block at LBA:%"
|
||||
PRIu64, i);
|
||||
GETLBASTATUS(sd, NULL, i, 24,
|
||||
logging(LOG_VERBOSE, "Read the status of the block at LBA:%"
|
||||
PRIu64, i);
|
||||
GETLBASTATUS(sd, NULL, i, 24,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Read the status of the block at LBA:%"
|
||||
PRIu64, i + lbppb);
|
||||
GETLBASTATUS(sd, &t, i + lbppb, 24,
|
||||
logging(LOG_VERBOSE, "Read the status of the block at LBA:%"
|
||||
PRIu64, i + lbppb);
|
||||
GETLBASTATUS(sd, &t, i + lbppb, 24,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (t == NULL) {
|
||||
CU_FAIL("[FAILED] GETLBASTATUS task is NULL");
|
||||
return;
|
||||
}
|
||||
lbas = scsi_datain_unmarshall(t);
|
||||
if (lbas == NULL) {
|
||||
CU_FAIL("[FAILED] GETLBASTATUS command: failed "
|
||||
"to unmarshall data.");
|
||||
scsi_free_scsi_task(t);
|
||||
return;
|
||||
}
|
||||
lbasd = &lbas->descriptors[0];
|
||||
if (lbasd->lba != i + lbppb) {
|
||||
CU_FAIL("[FAILED] GETLBASTATUS command: "
|
||||
"lba offset in first descriptor does not "
|
||||
"match request.");
|
||||
scsi_free_scsi_task(t);
|
||||
return;
|
||||
}
|
||||
if (lbasd->provisioning != SCSI_PROVISIONING_TYPE_MAPPED) {
|
||||
CU_FAIL("[FAILED] LBA should be mapped but isn't");
|
||||
return;
|
||||
}
|
||||
scsi_free_scsi_task(t);
|
||||
}
|
||||
if (t == NULL) {
|
||||
CU_FAIL("[FAILED] GETLBASTATUS task is NULL");
|
||||
return;
|
||||
}
|
||||
lbas = scsi_datain_unmarshall(t);
|
||||
if (lbas == NULL) {
|
||||
CU_FAIL("[FAILED] GETLBASTATUS command: failed "
|
||||
"to unmarshall data.");
|
||||
scsi_free_scsi_task(t);
|
||||
return;
|
||||
}
|
||||
lbasd = &lbas->descriptors[0];
|
||||
if (lbasd->lba != i + lbppb) {
|
||||
CU_FAIL("[FAILED] GETLBASTATUS command: "
|
||||
"lba offset in first descriptor does not "
|
||||
"match request.");
|
||||
scsi_free_scsi_task(t);
|
||||
return;
|
||||
}
|
||||
if (lbasd->provisioning != SCSI_PROVISIONING_TYPE_MAPPED) {
|
||||
CU_FAIL("[FAILED] LBA should be mapped but isn't");
|
||||
return;
|
||||
}
|
||||
scsi_free_scsi_task(t);
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test GETLBASTATUS for a single range of 1-255 "
|
||||
"blocks at offset 0");
|
||||
for (i = lbppb; i + lbppb <= 256; i += lbppb) {
|
||||
logging(LOG_VERBOSE, "Write the first %i blocks with a known "
|
||||
"pattern and thus map the blocks", (256 + lbppb));
|
||||
WRITE10(sd, 0, (256 + lbppb) * block_size,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test GETLBASTATUS for a single range of 1-255 "
|
||||
"blocks at offset 0");
|
||||
for (i = lbppb; i + lbppb <= 256; i += lbppb) {
|
||||
logging(LOG_VERBOSE, "Write the first %i blocks with a known "
|
||||
"pattern and thus map the blocks", (256 + lbppb));
|
||||
WRITE10(sd, 0, (256 + lbppb) * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Unmap %" PRIu64 " blocks at LBA 0", i);
|
||||
list[0].lba = 0;
|
||||
list[0].num = i;
|
||||
UNMAP(sd, 0, list, 1,
|
||||
logging(LOG_VERBOSE, "Unmap %" PRIu64 " blocks at LBA 0", i);
|
||||
list[0].lba = 0;
|
||||
list[0].num = i;
|
||||
UNMAP(sd, 0, list, 1,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Read the status of the block at LBA:0");
|
||||
logging(LOG_VERBOSE, "Read the status of the block at LBA:0");
|
||||
|
||||
GETLBASTATUS(sd, NULL, 0, 24,
|
||||
GETLBASTATUS(sd, NULL, 0, 24,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Read the status of the block at LBA:%" PRIu64, i + 1);
|
||||
GETLBASTATUS(sd, &t, i + 1, 24,
|
||||
logging(LOG_VERBOSE, "Read the status of the block at LBA:%" PRIu64, i + 1);
|
||||
GETLBASTATUS(sd, &t, i + 1, 24,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (t == NULL) {
|
||||
CU_FAIL("[FAILED] GETLBASTATUS task is NULL");
|
||||
return;
|
||||
}
|
||||
lbas = scsi_datain_unmarshall(t);
|
||||
if (lbas == NULL) {
|
||||
CU_FAIL("[FAILED] GETLBASTATUS command: failed "
|
||||
"to unmarshall data.");
|
||||
scsi_free_scsi_task(t);
|
||||
return;
|
||||
}
|
||||
lbasd = &lbas->descriptors[0];
|
||||
if (lbasd->lba != i + lbppb) {
|
||||
CU_FAIL("[FAILED] GETLBASTATUS command: "
|
||||
"lba offset in first descriptor does not "
|
||||
"match request.");
|
||||
scsi_free_scsi_task(t);
|
||||
return;
|
||||
}
|
||||
if (lbasd->provisioning != SCSI_PROVISIONING_TYPE_MAPPED) {
|
||||
CU_FAIL("[FAILED] LBA should be mapped but isn't");
|
||||
return;
|
||||
}
|
||||
scsi_free_scsi_task(t);
|
||||
}
|
||||
if (t == NULL) {
|
||||
CU_FAIL("[FAILED] GETLBASTATUS task is NULL");
|
||||
return;
|
||||
}
|
||||
lbas = scsi_datain_unmarshall(t);
|
||||
if (lbas == NULL) {
|
||||
CU_FAIL("[FAILED] GETLBASTATUS command: failed "
|
||||
"to unmarshall data.");
|
||||
scsi_free_scsi_task(t);
|
||||
return;
|
||||
}
|
||||
lbasd = &lbas->descriptors[0];
|
||||
if (lbasd->lba != i + lbppb) {
|
||||
CU_FAIL("[FAILED] GETLBASTATUS command: "
|
||||
"lba offset in first descriptor does not "
|
||||
"match request.");
|
||||
scsi_free_scsi_task(t);
|
||||
return;
|
||||
}
|
||||
if (lbasd->provisioning != SCSI_PROVISIONING_TYPE_MAPPED) {
|
||||
CU_FAIL("[FAILED] LBA should be mapped but isn't");
|
||||
return;
|
||||
}
|
||||
scsi_free_scsi_task(t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,85 +28,85 @@
|
||||
void
|
||||
test_inquiry_alloc_length(void)
|
||||
{
|
||||
int ret, i;
|
||||
struct scsi_inquiry_standard *std_inq;
|
||||
struct scsi_task *task2 = NULL;
|
||||
int ret, i;
|
||||
struct scsi_inquiry_standard *std_inq;
|
||||
struct scsi_task *task2 = NULL;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of the INQUIRY allocation length");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of the INQUIRY allocation length");
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can read standard INQUIRY page with alloc length from 5-255");
|
||||
for (i = 5; i < 256 ; i++) {
|
||||
if (task != NULL) {
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
}
|
||||
ret = inquiry(sd, &task, 0, 0, i,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify we got at least 36 bytes of data when reading with alloc length 255");
|
||||
CU_ASSERT(task->datain.size >= 36);
|
||||
logging(LOG_VERBOSE, "Verify we can read standard INQUIRY page with alloc length from 5-255");
|
||||
for (i = 5; i < 256 ; i++) {
|
||||
if (task != NULL) {
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
}
|
||||
ret = inquiry(sd, &task, 0, 0, i,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify we got at least 36 bytes of data when reading with alloc length 255");
|
||||
CU_ASSERT(task->datain.size >= 36);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can unmarshall the DATA-IN buffer");
|
||||
std_inq = scsi_datain_unmarshall(task);
|
||||
CU_ASSERT_NOT_EQUAL(std_inq, NULL);
|
||||
if (std_inq == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] Failed to unmarshall DATA-IN "
|
||||
"buffer");
|
||||
return;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify we can unmarshall the DATA-IN buffer");
|
||||
std_inq = scsi_datain_unmarshall(task);
|
||||
CU_ASSERT_NOT_EQUAL(std_inq, NULL);
|
||||
if (std_inq == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] Failed to unmarshall DATA-IN "
|
||||
"buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify peripheral-qualifier is 0");
|
||||
CU_ASSERT_EQUAL(std_inq->qualifier, 0);
|
||||
logging(LOG_VERBOSE, "Verify peripheral-qualifier is 0");
|
||||
CU_ASSERT_EQUAL(std_inq->qualifier, 0);
|
||||
|
||||
|
||||
|
||||
/* Final test. IF this claims SPC-3 or later then the target
|
||||
supports 16-bit allocation lengths. Try reading INQ data
|
||||
specifying 256 bytes as allocation length and make sure the
|
||||
target responds properly.
|
||||
*/
|
||||
logging(LOG_VERBOSE, "If version is SPC-3 or later INQUIRY supports 16-bit allocation lengths");
|
||||
switch (std_inq->version) {
|
||||
case 0x5:
|
||||
case 0x6:
|
||||
break;
|
||||
default:
|
||||
logging(LOG_NORMAL, "[SKIPPED] This device does not claim "
|
||||
"SPC-3 or later");
|
||||
CU_PASS("[SKIPPED] Not SPC-3 or later");
|
||||
goto finished;
|
||||
}
|
||||
/* Final test. IF this claims SPC-3 or later then the target
|
||||
supports 16-bit allocation lengths. Try reading INQ data
|
||||
specifying 256 bytes as allocation length and make sure the
|
||||
target responds properly.
|
||||
*/
|
||||
logging(LOG_VERBOSE, "If version is SPC-3 or later INQUIRY supports 16-bit allocation lengths");
|
||||
switch (std_inq->version) {
|
||||
case 0x5:
|
||||
case 0x6:
|
||||
break;
|
||||
default:
|
||||
logging(LOG_NORMAL, "[SKIPPED] This device does not claim "
|
||||
"SPC-3 or later");
|
||||
CU_PASS("[SKIPPED] Not SPC-3 or later");
|
||||
goto finished;
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
logging(LOG_VERBOSE, "Version is SPC-3 or later. Read INQUIRY data using 16-bit allocation length");
|
||||
logging(LOG_VERBOSE, "Read INQUIRY data with allocation length 511 (low order byte is 0xff)");
|
||||
ret = inquiry(sd, &task, 0, 0, 511,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "Version is SPC-3 or later. Read INQUIRY data using 16-bit allocation length");
|
||||
logging(LOG_VERBOSE, "Read INQUIRY data with allocation length 511 (low order byte is 0xff)");
|
||||
ret = inquiry(sd, &task, 0, 0, 511,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Read INQUIRY data with allocation length 512 (low order byte is 0x00)");
|
||||
ret = inquiry(sd, &task2, 0, 0, 512,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "Read INQUIRY data with allocation length 512 (low order byte is 0x00)");
|
||||
ret = inquiry(sd, &task2, 0, 0, 512,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "INQUIRY data should be the same when allocation length is 511 and 512 bytes");
|
||||
ret = task->datain.size != task2->datain.size;
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
ret = memcmp(task->datain.data, task2->datain.data, task->datain.size);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "INQUIRY data should be the same when allocation length is 511 and 512 bytes");
|
||||
ret = task->datain.size != task2->datain.size;
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
ret = memcmp(task->datain.data, task2->datain.data, task->datain.size);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
|
||||
finished:
|
||||
if (task != NULL) {
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
}
|
||||
if (task2 != NULL) {
|
||||
scsi_free_scsi_task(task2);
|
||||
task2 = NULL;
|
||||
}
|
||||
if (task != NULL) {
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
}
|
||||
if (task2 != NULL) {
|
||||
scsi_free_scsi_task(task2);
|
||||
task2 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,158 +27,158 @@
|
||||
|
||||
static void check_lbp(int *supports_lbp)
|
||||
{
|
||||
*supports_lbp = 0;
|
||||
*supports_lbp = 0;
|
||||
|
||||
CHECK_FOR_THIN_PROVISIONING;
|
||||
CHECK_FOR_THIN_PROVISIONING;
|
||||
|
||||
*supports_lbp = 1;
|
||||
*supports_lbp = 1;
|
||||
}
|
||||
|
||||
void
|
||||
test_inquiry_block_limits(void)
|
||||
{
|
||||
int supports_lbp, ret;
|
||||
struct scsi_inquiry_block_limits *bl;
|
||||
struct scsi_task *bl_task = NULL;
|
||||
struct scsi_inquiry_logical_block_provisioning *lbp = NULL;
|
||||
struct scsi_task *lbp_task = NULL;
|
||||
int supports_lbp, ret;
|
||||
struct scsi_inquiry_block_limits *bl;
|
||||
struct scsi_task *bl_task = NULL;
|
||||
struct scsi_inquiry_logical_block_provisioning *lbp = NULL;
|
||||
struct scsi_task *lbp_task = NULL;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of the INQUIRY Block Limits");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of the INQUIRY Block Limits");
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
logging(LOG_VERBOSE, "Block device. Verify that we can read Block "
|
||||
"Limits VPD");
|
||||
ret = inquiry(sd, &bl_task,
|
||||
1, SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret != 0) {
|
||||
logging(LOG_NORMAL, "[FAILURE] failed to send inquiry.");
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Block device. Verify that we can read Block "
|
||||
"Limits VPD");
|
||||
ret = inquiry(sd, &bl_task,
|
||||
1, SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret != 0) {
|
||||
logging(LOG_NORMAL, "[FAILURE] failed to send inquiry.");
|
||||
goto finished;
|
||||
}
|
||||
|
||||
bl = scsi_datain_unmarshall(bl_task);
|
||||
if (bl == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILURE] failed to unmarshall inquiry "
|
||||
"datain blob.");
|
||||
CU_FAIL("[FAILURE] failed to unmarshall inquiry "
|
||||
"datain blob.");
|
||||
goto finished;
|
||||
}
|
||||
bl = scsi_datain_unmarshall(bl_task);
|
||||
if (bl == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILURE] failed to unmarshall inquiry "
|
||||
"datain blob.");
|
||||
CU_FAIL("[FAILURE] failed to unmarshall inquiry "
|
||||
"datain blob.");
|
||||
goto finished;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the PageLength matches up with the "
|
||||
"size of the DATA-IN buffer.");
|
||||
CU_ASSERT_EQUAL(bl_task->datain.size, bl_task->datain.data[3] + 4);
|
||||
if (bl_task->datain.size != bl_task->datain.data[3] + 4) {
|
||||
logging(LOG_NORMAL, "[FAILURE] Invalid PageLength returned. "
|
||||
"Was %d but expected %d",
|
||||
bl_task->datain.data[3], bl_task->datain.size - 4);
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] PageLength matches DataIn "
|
||||
"buffer size");
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify that the PageLength matches up with the "
|
||||
"size of the DATA-IN buffer.");
|
||||
CU_ASSERT_EQUAL(bl_task->datain.size, bl_task->datain.data[3] + 4);
|
||||
if (bl_task->datain.size != bl_task->datain.data[3] + 4) {
|
||||
logging(LOG_NORMAL, "[FAILURE] Invalid PageLength returned. "
|
||||
"Was %d but expected %d",
|
||||
bl_task->datain.data[3], bl_task->datain.size - 4);
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] PageLength matches DataIn "
|
||||
"buffer size");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the PageLength matches SCSI-level.");
|
||||
/* if it is not SBC3 then we assume it must be SBC2 */
|
||||
if (sbc3_support) {
|
||||
logging(LOG_VERBOSE, "Device claims SBC-3. Verify that " "page size is >= 60");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "Device is not SBC-3. Verify that "
|
||||
"PageLength == 8 (but allow >= 60 too. Some SBC-2 "
|
||||
"devices support some SBC-3 features.");
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify that the PageLength matches SCSI-level.");
|
||||
/* if it is not SBC3 then we assume it must be SBC2 */
|
||||
if (sbc3_support) {
|
||||
logging(LOG_VERBOSE, "Device claims SBC-3. Verify that " "page size is >= 60");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "Device is not SBC-3. Verify that "
|
||||
"PageLength == 8 (but allow >= 60 too. Some SBC-2 "
|
||||
"devices support some SBC-3 features.");
|
||||
}
|
||||
|
||||
if (bl_task->datain.data[3] == 8) {
|
||||
if (sbc3_support) {
|
||||
logging(LOG_NORMAL, "[FAILURE] Invalid PageLength "
|
||||
"returned. SBC3 claimed but page length "
|
||||
"is 8.");
|
||||
CU_FAIL("[FAILED] Invalid pagelength returned. "
|
||||
"SBC3 claimed but page length is 8.");
|
||||
}
|
||||
} else if (bl_task->datain.size >= 60) {
|
||||
if (!sbc3_support) {
|
||||
logging(LOG_NORMAL, "[WARNING] SBC-3 pagelength "
|
||||
"(>=60) returned but SBC-3 support was not "
|
||||
"claimed in the standard inquiry page.");
|
||||
CU_FAIL("[WARNING] SBC-3 pagelength "
|
||||
"(>=60) returned but SBC-3 support was not "
|
||||
"claimed in the standard inquiry page.");
|
||||
}
|
||||
}
|
||||
if (bl_task->datain.data[3] == 8) {
|
||||
if (sbc3_support) {
|
||||
logging(LOG_NORMAL, "[FAILURE] Invalid PageLength "
|
||||
"returned. SBC3 claimed but page length "
|
||||
"is 8.");
|
||||
CU_FAIL("[FAILED] Invalid pagelength returned. "
|
||||
"SBC3 claimed but page length is 8.");
|
||||
}
|
||||
} else if (bl_task->datain.size >= 60) {
|
||||
if (!sbc3_support) {
|
||||
logging(LOG_NORMAL, "[WARNING] SBC-3 pagelength "
|
||||
"(>=60) returned but SBC-3 support was not "
|
||||
"claimed in the standard inquiry page.");
|
||||
CU_FAIL("[WARNING] SBC-3 pagelength "
|
||||
"(>=60) returned but SBC-3 support was not "
|
||||
"claimed in the standard inquiry page.");
|
||||
}
|
||||
}
|
||||
|
||||
if (bl_task->datain.data[3] != 0x3c) {
|
||||
goto finished;
|
||||
}
|
||||
if (bl_task->datain.data[3] != 0x3c) {
|
||||
goto finished;
|
||||
}
|
||||
|
||||
check_lbp(&supports_lbp);
|
||||
if (!supports_lbp)
|
||||
goto finished;
|
||||
check_lbp(&supports_lbp);
|
||||
if (!supports_lbp)
|
||||
goto finished;
|
||||
|
||||
/*
|
||||
* MAXIMUM UNMAP LBA COUNT
|
||||
* MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT
|
||||
*/
|
||||
logging(LOG_VERBOSE, "Try reading the logical block provisioning VPD");
|
||||
ret = inquiry(sd, &lbp_task,
|
||||
1, SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (ret == 0) {
|
||||
lbp = scsi_datain_unmarshall(lbp_task);
|
||||
if (lbp == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILURE] failed to unmarshall "
|
||||
"inquiry datain blob.");
|
||||
}
|
||||
}
|
||||
/*
|
||||
* MAXIMUM UNMAP LBA COUNT
|
||||
* MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT
|
||||
*/
|
||||
logging(LOG_VERBOSE, "Try reading the logical block provisioning VPD");
|
||||
ret = inquiry(sd, &lbp_task,
|
||||
1, SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (ret == 0) {
|
||||
lbp = scsi_datain_unmarshall(lbp_task);
|
||||
if (lbp == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILURE] failed to unmarshall "
|
||||
"inquiry datain blob.");
|
||||
}
|
||||
}
|
||||
|
||||
if (lbp && lbp->lbpu) {
|
||||
/* We support UNMAP so MAXIMUM UNMAP LBA COUNT and
|
||||
* MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT.
|
||||
* They must be > 0.
|
||||
* It can be 0xffffffff which means no limit, but if there is
|
||||
* an explicit limit set, then we check that it looks sane.
|
||||
* Sane here means < 1M.
|
||||
*/
|
||||
logging(LOG_VERBOSE, "Device claims UNMAP support via LBPU");
|
||||
logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP LBA COUNT is "
|
||||
"not 0");
|
||||
CU_ASSERT_NOT_EQUAL(bl->max_unmap, 0);
|
||||
if (lbp && lbp->lbpu) {
|
||||
/* We support UNMAP so MAXIMUM UNMAP LBA COUNT and
|
||||
* MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT.
|
||||
* They must be > 0.
|
||||
* It can be 0xffffffff which means no limit, but if there is
|
||||
* an explicit limit set, then we check that it looks sane.
|
||||
* Sane here means < 1M.
|
||||
*/
|
||||
logging(LOG_VERBOSE, "Device claims UNMAP support via LBPU");
|
||||
logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP LBA COUNT is "
|
||||
"not 0");
|
||||
CU_ASSERT_NOT_EQUAL(bl->max_unmap, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP LBA COUNT is "
|
||||
"at least 2^LBPPBE");
|
||||
CU_ASSERT_EQUAL(bl->max_unmap >= (1U << rc16->lbppbe), 1);
|
||||
logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP LBA COUNT is "
|
||||
"at least 2^LBPPBE");
|
||||
CU_ASSERT_EQUAL(bl->max_unmap >= (1U << rc16->lbppbe), 1);
|
||||
|
||||
if (bl->max_unmap != 0xffffffff) {
|
||||
logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP LBA "
|
||||
"COUNT is not insanely big");
|
||||
CU_ASSERT_TRUE(bl->max_unmap <= 1024*1024);
|
||||
}
|
||||
if (bl->max_unmap != 0xffffffff) {
|
||||
logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP LBA "
|
||||
"COUNT is not insanely big");
|
||||
CU_ASSERT_TRUE(bl->max_unmap <= 1024*1024);
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP BLOCK "
|
||||
"DESCRIPTOR COUNT is not 0");
|
||||
CU_ASSERT_NOT_EQUAL(bl->max_unmap_bdc, 0);
|
||||
if (bl->max_unmap_bdc != 0xffffffff) {
|
||||
logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP "
|
||||
"BLOCK DESCRIPTOR COUNT is not insanely big");
|
||||
CU_ASSERT_TRUE(bl->max_unmap_bdc <= 1024*1024);
|
||||
}
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "Device does not claim UNMAP support via "
|
||||
"LBPU");
|
||||
logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP LBA COUNT is "
|
||||
"0");
|
||||
CU_ASSERT_EQUAL(bl->max_unmap, 0);
|
||||
logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP BLOCK "
|
||||
"DESCRIPTOR COUNT is not 0");
|
||||
CU_ASSERT_NOT_EQUAL(bl->max_unmap_bdc, 0);
|
||||
if (bl->max_unmap_bdc != 0xffffffff) {
|
||||
logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP "
|
||||
"BLOCK DESCRIPTOR COUNT is not insanely big");
|
||||
CU_ASSERT_TRUE(bl->max_unmap_bdc <= 1024*1024);
|
||||
}
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "Device does not claim UNMAP support via "
|
||||
"LBPU");
|
||||
logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP LBA COUNT is "
|
||||
"0");
|
||||
CU_ASSERT_EQUAL(bl->max_unmap, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP BLOCK "
|
||||
"DESCRIPTOR COUNT is 0");
|
||||
CU_ASSERT_EQUAL(bl->max_unmap_bdc, 0);
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify that MAXIMUM UNMAP BLOCK "
|
||||
"DESCRIPTOR COUNT is 0");
|
||||
CU_ASSERT_EQUAL(bl->max_unmap_bdc, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
finished:
|
||||
scsi_free_scsi_task(bl_task);
|
||||
scsi_free_scsi_task(lbp_task);
|
||||
scsi_free_scsi_task(bl_task);
|
||||
scsi_free_scsi_task(lbp_task);
|
||||
}
|
||||
|
||||
@@ -28,13 +28,13 @@
|
||||
void
|
||||
test_inquiry_evpd(void)
|
||||
{
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of the INQUIRY EVPD bit");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of the INQUIRY EVPD bit");
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that INQUIRY with EVPD==0 and PC!=0 is an error");
|
||||
ret = inquiry(sd, NULL, 0, 1, 256,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "Verify that INQUIRY with EVPD==0 and PC!=0 is an error");
|
||||
ret = inquiry(sd, NULL, 0, 1, 256,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
|
||||
@@ -28,23 +28,23 @@
|
||||
void
|
||||
test_inquiry_mandatory_vpd_sbc(void)
|
||||
{
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test INQUIRY support for mandatory SBC VPD");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test INQUIRY support for mandatory SBC VPD");
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "SUPPORTED_VPD_PAGES is mandatory for SBC devices. Verify we can read it.");
|
||||
ret = inquiry(sd, NULL,
|
||||
1, SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "SUPPORTED_VPD_PAGES is mandatory for SBC devices. Verify we can read it.");
|
||||
ret = inquiry(sd, NULL,
|
||||
1, SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "DEVICE_IDENTIFICATION is mandatory for SBC devices. Verify we can read it.");
|
||||
ret = inquiry(sd, NULL,
|
||||
1, SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "DEVICE_IDENTIFICATION is mandatory for SBC devices. Verify we can read it.");
|
||||
ret = inquiry(sd, NULL,
|
||||
1, SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
|
||||
@@ -28,150 +28,150 @@
|
||||
void
|
||||
test_inquiry_standard(void)
|
||||
{
|
||||
int ret, i;
|
||||
struct scsi_inquiry_standard *std_inq;
|
||||
int ret, i;
|
||||
struct scsi_inquiry_standard *std_inq;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of the standard INQUIRY page");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of the standard INQUIRY page");
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can read standard INQUIRY page");
|
||||
/* 260 bytes is the maximum possible size of the standard vpd */
|
||||
ret = inquiry(sd, &task, 0, 0, 260,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "Verify we can read standard INQUIRY page");
|
||||
/* 260 bytes is the maximum possible size of the standard vpd */
|
||||
ret = inquiry(sd, &task, 0, 0, 260,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got at least 36 bytes of data");
|
||||
CU_ASSERT(task->datain.size >= 36);
|
||||
logging(LOG_VERBOSE, "Verify we got at least 36 bytes of data");
|
||||
CU_ASSERT(task->datain.size >= 36);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can unmarshall the DATA-IN buffer");
|
||||
std_inq = scsi_datain_unmarshall(task);
|
||||
CU_ASSERT_NOT_EQUAL(std_inq, NULL);
|
||||
if (std_inq == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] Failed to unmarshall DATA-IN "
|
||||
"buffer");
|
||||
return;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify we can unmarshall the DATA-IN buffer");
|
||||
std_inq = scsi_datain_unmarshall(task);
|
||||
CU_ASSERT_NOT_EQUAL(std_inq, NULL);
|
||||
if (std_inq == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] Failed to unmarshall DATA-IN "
|
||||
"buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify peripheral-qualifier is 0");
|
||||
CU_ASSERT_EQUAL(std_inq->qualifier, 0);
|
||||
logging(LOG_VERBOSE, "Verify peripheral-qualifier is 0");
|
||||
CU_ASSERT_EQUAL(std_inq->qualifier, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify version field is either 0x4, 0x5 or 0x6");
|
||||
switch (std_inq->version) {
|
||||
case 0x0:
|
||||
logging(LOG_NORMAL, "[WARNING] Standard INQUIRY data claims "
|
||||
"conformance to no standard. Version==0. "
|
||||
"Bad sport.");
|
||||
logging(LOG_VERBOSE, "Verify version field is either 0x4, 0x5 or 0x6");
|
||||
switch (std_inq->version) {
|
||||
case 0x0:
|
||||
logging(LOG_NORMAL, "[WARNING] Standard INQUIRY data claims "
|
||||
"conformance to no standard. Version==0. "
|
||||
"Bad sport.");
|
||||
|
||||
break;
|
||||
case 0x4:
|
||||
case 0x5:
|
||||
case 0x6:
|
||||
break;
|
||||
default:
|
||||
logging(LOG_NORMAL, "[FAILED] Invalid version in standard "
|
||||
"INQUIRY data. Version %d found but only versions "
|
||||
"0x4,0x4,0x6 are valid.", std_inq->version);
|
||||
CU_FAIL("Invalid version in INQUIRY data");
|
||||
}
|
||||
break;
|
||||
case 0x4:
|
||||
case 0x5:
|
||||
case 0x6:
|
||||
break;
|
||||
default:
|
||||
logging(LOG_NORMAL, "[FAILED] Invalid version in standard "
|
||||
"INQUIRY data. Version %d found but only versions "
|
||||
"0x4,0x4,0x6 are valid.", std_inq->version);
|
||||
CU_FAIL("Invalid version in INQUIRY data");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify response-data-format is 2 "
|
||||
"(SPC-2 or later)");
|
||||
if (std_inq->response_data_format != 2) {
|
||||
logging(LOG_NORMAL, "[FAILED] Response data format is "
|
||||
"invalid. Must be 2 but device returned %d",
|
||||
std_inq->response_data_format);
|
||||
}
|
||||
CU_ASSERT_EQUAL(std_inq->response_data_format, 2);
|
||||
logging(LOG_VERBOSE, "Verify response-data-format is 2 "
|
||||
"(SPC-2 or later)");
|
||||
if (std_inq->response_data_format != 2) {
|
||||
logging(LOG_NORMAL, "[FAILED] Response data format is "
|
||||
"invalid. Must be 2 but device returned %d",
|
||||
std_inq->response_data_format);
|
||||
}
|
||||
CU_ASSERT_EQUAL(std_inq->response_data_format, 2);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify additional-length is correct");
|
||||
if (std_inq->additional_length > task->datain.size - 5) {
|
||||
logging(LOG_NORMAL, "[FAILED] Bad additional length "
|
||||
"returned. Should be %d but device returned %d.",
|
||||
task->datain.size - 5,
|
||||
std_inq->additional_length);
|
||||
logging(LOG_NORMAL, "[FAILED] Additional length points "
|
||||
"beyond end of data");
|
||||
CU_FAIL("Additional length points beyond end of data");
|
||||
}
|
||||
if (std_inq->additional_length < task->datain.size - 5) {
|
||||
logging(LOG_NORMAL, "[WARNING] Bad additional length "
|
||||
"returned. Should be %d but device returned %d. ",
|
||||
task->datain.size - 5,
|
||||
std_inq->additional_length);
|
||||
logging(LOG_VERBOSE, "Verify that all padding data is 0");
|
||||
for (i = std_inq->additional_length + 6; i < task->datain.size; i++) {
|
||||
if (!task->datain.data[i])
|
||||
continue;
|
||||
logging(LOG_NORMAL, "[FAILED] Padding data is not zero."
|
||||
" Are we leaking data?");
|
||||
CU_FAIL("Padding data is not zero. Leaking data?");
|
||||
}
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify additional-length is correct");
|
||||
if (std_inq->additional_length > task->datain.size - 5) {
|
||||
logging(LOG_NORMAL, "[FAILED] Bad additional length "
|
||||
"returned. Should be %d but device returned %d.",
|
||||
task->datain.size - 5,
|
||||
std_inq->additional_length);
|
||||
logging(LOG_NORMAL, "[FAILED] Additional length points "
|
||||
"beyond end of data");
|
||||
CU_FAIL("Additional length points beyond end of data");
|
||||
}
|
||||
if (std_inq->additional_length < task->datain.size - 5) {
|
||||
logging(LOG_NORMAL, "[WARNING] Bad additional length "
|
||||
"returned. Should be %d but device returned %d. ",
|
||||
task->datain.size - 5,
|
||||
std_inq->additional_length);
|
||||
logging(LOG_VERBOSE, "Verify that all padding data is 0");
|
||||
for (i = std_inq->additional_length + 6; i < task->datain.size; i++) {
|
||||
if (!task->datain.data[i])
|
||||
continue;
|
||||
logging(LOG_NORMAL, "[FAILED] Padding data is not zero."
|
||||
" Are we leaking data?");
|
||||
CU_FAIL("Padding data is not zero. Leaking data?");
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify VENDOR_IDENTIFICATION is in ASCII");
|
||||
for (i = 8; i < 16; i++) {
|
||||
/* SPC-4 4.4.1 only characters 0x00 and 0x20-0x7E allowed */
|
||||
if (task->datain.data[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
if (task->datain.data[i] >= 0x20 && task->datain.data[i] <= 0x7e) {
|
||||
continue;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify VENDOR_IDENTIFICATION is in ASCII");
|
||||
for (i = 8; i < 16; i++) {
|
||||
/* SPC-4 4.4.1 only characters 0x00 and 0x20-0x7E allowed */
|
||||
if (task->datain.data[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
if (task->datain.data[i] >= 0x20 && task->datain.data[i] <= 0x7e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
logging(LOG_NORMAL, "[FAILED] VENDOR_IDENTIFICATION contains "
|
||||
"non-ASCII characters");
|
||||
CU_FAIL("Invalid characters in VENDOR_IDENTIFICATION");
|
||||
break;
|
||||
}
|
||||
logging(LOG_NORMAL, "[FAILED] VENDOR_IDENTIFICATION contains "
|
||||
"non-ASCII characters");
|
||||
CU_FAIL("Invalid characters in VENDOR_IDENTIFICATION");
|
||||
break;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify PRODUCT_IDENTIFICATION is in ASCII");
|
||||
for (i = 16; i < 32; i++) {
|
||||
/* SPC-4 4.4.1 only characters 0x00 and 0x20-0x7E allowed */
|
||||
if (task->datain.data[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
if (task->datain.data[i] >= 0x20 && task->datain.data[i] <= 0x7e) {
|
||||
continue;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify PRODUCT_IDENTIFICATION is in ASCII");
|
||||
for (i = 16; i < 32; i++) {
|
||||
/* SPC-4 4.4.1 only characters 0x00 and 0x20-0x7E allowed */
|
||||
if (task->datain.data[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
if (task->datain.data[i] >= 0x20 && task->datain.data[i] <= 0x7e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
logging(LOG_NORMAL, "[FAILED] PRODUCT_IDENTIFICATION contains "
|
||||
"non-ASCII characters");
|
||||
CU_FAIL("Invalid characters in PRODUCT_IDENTIFICATION");
|
||||
break;
|
||||
}
|
||||
logging(LOG_NORMAL, "[FAILED] PRODUCT_IDENTIFICATION contains "
|
||||
"non-ASCII characters");
|
||||
CU_FAIL("Invalid characters in PRODUCT_IDENTIFICATION");
|
||||
break;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify PRODUCT_REVISION_LEVEL is in ASCII");
|
||||
for (i = 32; i < 36; i++) {
|
||||
/* SPC-4 4.4.1 only characters 0x00 and 0x20-0x7E allowed */
|
||||
if (task->datain.data[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
if (task->datain.data[i] >= 0x20 && task->datain.data[i] <= 0x7e) {
|
||||
continue;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify PRODUCT_REVISION_LEVEL is in ASCII");
|
||||
for (i = 32; i < 36; i++) {
|
||||
/* SPC-4 4.4.1 only characters 0x00 and 0x20-0x7E allowed */
|
||||
if (task->datain.data[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
if (task->datain.data[i] >= 0x20 && task->datain.data[i] <= 0x7e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
logging(LOG_NORMAL, "[FAILED] PRODUCT_REVISON_LEVEL contains "
|
||||
"non-ASCII characters");
|
||||
CU_FAIL("Invalid characters in PRODUCT_REVISON_LEVEL");
|
||||
break;
|
||||
}
|
||||
logging(LOG_NORMAL, "[FAILED] PRODUCT_REVISON_LEVEL contains "
|
||||
"non-ASCII characters");
|
||||
CU_FAIL("Invalid characters in PRODUCT_REVISON_LEVEL");
|
||||
break;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify AERC is clear in SPC-3 and later");
|
||||
if (task->datain.data[3] & 0x80 && std_inq->version >= 5) {
|
||||
logging(LOG_NORMAL, "[FAILED] AERC is set but this device "
|
||||
"reports SPC-3 or later.");
|
||||
CU_FAIL("AERC is set but SPC-3+ is claimed");
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify AERC is clear in SPC-3 and later");
|
||||
if (task->datain.data[3] & 0x80 && std_inq->version >= 5) {
|
||||
logging(LOG_NORMAL, "[FAILED] AERC is set but this device "
|
||||
"reports SPC-3 or later.");
|
||||
CU_FAIL("AERC is set but SPC-3+ is claimed");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify TRMTSK is clear in SPC-2 and later");
|
||||
if (task->datain.data[3] & 0x40 && std_inq->version >= 4) {
|
||||
logging(LOG_NORMAL, "[FAILED] TRMTSK is set but this device "
|
||||
"reports SPC-2 or later.");
|
||||
CU_FAIL("TRMTSK is set but SPC-2+ is claimed");
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify TRMTSK is clear in SPC-2 and later");
|
||||
if (task->datain.data[3] & 0x40 && std_inq->version >= 4) {
|
||||
logging(LOG_NORMAL, "[FAILED] TRMTSK is set but this device "
|
||||
"reports SPC-2 or later.");
|
||||
CU_FAIL("TRMTSK is set but SPC-2+ is claimed");
|
||||
}
|
||||
|
||||
if (task != NULL) {
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
}
|
||||
if (task != NULL) {
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,42 +28,42 @@
|
||||
void
|
||||
test_inquiry_supported_vpd(void)
|
||||
{
|
||||
int ret, i;
|
||||
struct scsi_inquiry_supported_pages *sup_inq;
|
||||
int ret, i;
|
||||
struct scsi_inquiry_supported_pages *sup_inq;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test INQUIRY supported VPD pages");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test INQUIRY supported VPD pages");
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can read the SUPPORTED VPD page");
|
||||
ret = inquiry(sd, &task,
|
||||
1, SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "Verify we can read the SUPPORTED VPD page");
|
||||
ret = inquiry(sd, &task,
|
||||
1, SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got at least 4 bytes of data");
|
||||
CU_ASSERT(task->datain.size >= 4);
|
||||
logging(LOG_VERBOSE, "Verify we got at least 4 bytes of data");
|
||||
CU_ASSERT(task->datain.size >= 4);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can unmarshall the DATA-IN buffer");
|
||||
sup_inq = scsi_datain_unmarshall(task);
|
||||
CU_ASSERT_NOT_EQUAL(sup_inq, NULL);
|
||||
if (sup_inq == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] Failed to unmarshall DATA-IN "
|
||||
"buffer");
|
||||
return;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify we can unmarshall the DATA-IN buffer");
|
||||
sup_inq = scsi_datain_unmarshall(task);
|
||||
CU_ASSERT_NOT_EQUAL(sup_inq, NULL);
|
||||
if (sup_inq == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] Failed to unmarshall DATA-IN "
|
||||
"buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we read all the supported pages");
|
||||
for (i = 0; i < sup_inq->num_pages; i++) {
|
||||
logging(LOG_VERBOSE, "Verify we can read page 0x%02x",
|
||||
sup_inq->pages[i]);
|
||||
logging(LOG_VERBOSE, "Verify we read all the supported pages");
|
||||
for (i = 0; i < sup_inq->num_pages; i++) {
|
||||
logging(LOG_VERBOSE, "Verify we can read page 0x%02x",
|
||||
sup_inq->pages[i]);
|
||||
|
||||
ret = inquiry(sd, NULL, 1, sup_inq->pages[i], 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
ret = inquiry(sd, NULL, 1, sup_inq->pages[i], 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
|
||||
if (task != NULL) {
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
}
|
||||
if (task != NULL) {
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,80 +28,80 @@
|
||||
void
|
||||
test_inquiry_version_descriptors(void)
|
||||
{
|
||||
int i, claimed_ok;
|
||||
int i, claimed_ok;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of the INQUIRY version descriptors");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of the INQUIRY version descriptors");
|
||||
|
||||
switch (inq->device_type) {
|
||||
case SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS:
|
||||
logging(LOG_VERBOSE, "Device is a block device");
|
||||
switch (inq->device_type) {
|
||||
case SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS:
|
||||
logging(LOG_VERBOSE, "Device is a block device");
|
||||
|
||||
logging(LOG_VERBOSE, "Verify it claim some version of SPC");
|
||||
claimed_ok = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
switch(inq->version_descriptor[i]) {
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_ANSI_INCITS_301_1997:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_T10_0995_D_R11A:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_2:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_2_ISO_IEC_14776_452:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_2_ANSI_INCITS_351_2001:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_2_T10_1236_D_R20:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_2_T10_1236_D_R12:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_2_T10_1236_D_R18:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_2_T10_1236_D_R19:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_3:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_3_ISO_IEC_14776_453:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_3_ANSI_INCITS_408_2005:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_3_T10_1416_D_R7:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_3_T10_1416_D_R21:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_3_T10_1416_D_R22:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_3_T10_1416_D_R23:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_4:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_4_T10_1731_D_R16:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_4_T10_1731_D_R18:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_4_T10_1731_D_R23:
|
||||
claimed_ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (claimed_ok == 0) {
|
||||
logging(LOG_NORMAL, "[WARNING] Block device "
|
||||
"did not claim any version of SPC");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Block device "
|
||||
"claimed a version of SPC");
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify it claim some version of SPC");
|
||||
claimed_ok = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
switch(inq->version_descriptor[i]) {
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_ANSI_INCITS_301_1997:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_T10_0995_D_R11A:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_2:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_2_ISO_IEC_14776_452:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_2_ANSI_INCITS_351_2001:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_2_T10_1236_D_R20:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_2_T10_1236_D_R12:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_2_T10_1236_D_R18:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_2_T10_1236_D_R19:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_3:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_3_ISO_IEC_14776_453:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_3_ANSI_INCITS_408_2005:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_3_T10_1416_D_R7:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_3_T10_1416_D_R21:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_3_T10_1416_D_R22:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_3_T10_1416_D_R23:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_4:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_4_T10_1731_D_R16:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_4_T10_1731_D_R18:
|
||||
case SCSI_VERSION_DESCRIPTOR_SPC_4_T10_1731_D_R23:
|
||||
claimed_ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (claimed_ok == 0) {
|
||||
logging(LOG_NORMAL, "[WARNING] Block device "
|
||||
"did not claim any version of SPC");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Block device "
|
||||
"claimed a version of SPC");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify it claim some version of SBC");
|
||||
claimed_ok = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
switch(inq->version_descriptor[i]) {
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_ANSI_INCITS_306_1998:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_T10_0996_D_R08C:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_2:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_2_ISO_IEC_14776_322:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_2_ANSI_INCITS_405_2005:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_2_T10_1417_D_R16:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_2_T10_1417_D_R5A:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_2_T10_1417_D_R15:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_3:
|
||||
claimed_ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (claimed_ok == 0) {
|
||||
logging(LOG_NORMAL, "[WARNING] Block device "
|
||||
"did not claim any version of SBC");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Block device "
|
||||
"claimed a version of SBC");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logging(LOG_VERBOSE, "No version descriptor tests for device"
|
||||
" type %d yet.", inq->device_type);
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify it claim some version of SBC");
|
||||
claimed_ok = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
switch(inq->version_descriptor[i]) {
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_ANSI_INCITS_306_1998:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_T10_0996_D_R08C:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_2:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_2_ISO_IEC_14776_322:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_2_ANSI_INCITS_405_2005:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_2_T10_1417_D_R16:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_2_T10_1417_D_R5A:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_2_T10_1417_D_R15:
|
||||
case SCSI_VERSION_DESCRIPTOR_SBC_3:
|
||||
claimed_ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (claimed_ok == 0) {
|
||||
logging(LOG_NORMAL, "[WARNING] Block device "
|
||||
"did not claim any version of SBC");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Block device "
|
||||
"claimed a version of SBC");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logging(LOG_VERBOSE, "No version descriptor tests for device"
|
||||
" type %d yet.", inq->device_type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,62 +29,62 @@ static int change_cmdsn;
|
||||
|
||||
static int my_iscsi_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
|
||||
{
|
||||
switch (change_cmdsn) {
|
||||
case 1:
|
||||
/* change the cmdsn so it becomes too big */
|
||||
scsi_set_uint32(&pdu->outdata.data[24], iscsi->maxcmdsn + 1);
|
||||
/* fudge the cmdsn value back to where it should be if this
|
||||
* pdu is ignored.
|
||||
*/
|
||||
iscsi->cmdsn = iscsi->expcmdsn;
|
||||
break;
|
||||
}
|
||||
switch (change_cmdsn) {
|
||||
case 1:
|
||||
/* change the cmdsn so it becomes too big */
|
||||
scsi_set_uint32(&pdu->outdata.data[24], iscsi->maxcmdsn + 1);
|
||||
/* fudge the cmdsn value back to where it should be if this
|
||||
* pdu is ignored.
|
||||
*/
|
||||
iscsi->cmdsn = iscsi->expcmdsn;
|
||||
break;
|
||||
}
|
||||
|
||||
change_cmdsn = 0;
|
||||
return 0;
|
||||
change_cmdsn = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_iscsi_cmdsn_toohigh(void)
|
||||
{
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test sending invalid iSCSI CMDSN");
|
||||
logging(LOG_VERBOSE, "CMDSN MUST be in the range EXPCMDSN and MAXCMDSN");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test sending invalid iSCSI CMDSN");
|
||||
logging(LOG_VERBOSE, "CMDSN MUST be in the range EXPCMDSN and MAXCMDSN");
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "RFC3720:3.2.2.1 CMDSN > MAXCMDSN must be silently ignored by the target");
|
||||
logging(LOG_VERBOSE, "Send a TESTUNITREADY with CMDSN == MAXCMDSN+1. Should be ignored by the target.");
|
||||
logging(LOG_VERBOSE, "RFC3720:3.2.2.1 CMDSN > MAXCMDSN must be silently ignored by the target");
|
||||
logging(LOG_VERBOSE, "Send a TESTUNITREADY with CMDSN == MAXCMDSN+1. Should be ignored by the target.");
|
||||
|
||||
sd->iscsi_ctx->use_immediate_data = ISCSI_IMMEDIATE_DATA_NO;
|
||||
sd->iscsi_ctx->target_max_recv_data_segment_length = block_size;
|
||||
local_iscsi_queue_pdu = my_iscsi_queue_pdu;
|
||||
change_cmdsn = 1;
|
||||
/* we don't want autoreconnect since some targets will incorrectly
|
||||
* drop the connection on this condition.
|
||||
*/
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
iscsi_set_timeout(sd->iscsi_ctx, 3);
|
||||
sd->iscsi_ctx->use_immediate_data = ISCSI_IMMEDIATE_DATA_NO;
|
||||
sd->iscsi_ctx->target_max_recv_data_segment_length = block_size;
|
||||
local_iscsi_queue_pdu = my_iscsi_queue_pdu;
|
||||
change_cmdsn = 1;
|
||||
/* we don't want autoreconnect since some targets will incorrectly
|
||||
* drop the connection on this condition.
|
||||
*/
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
iscsi_set_timeout(sd->iscsi_ctx, 3);
|
||||
|
||||
ret = testunitready(sd,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, -1);
|
||||
if (ret == -1) {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] We did not receive a reply");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[FAILURE] We got a response from the target but SMDSN was outside of the window.");
|
||||
}
|
||||
ret = testunitready(sd,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, -1);
|
||||
if (ret == -1) {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] We did not receive a reply");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[FAILURE] We got a response from the target but SMDSN was outside of the window.");
|
||||
}
|
||||
|
||||
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
logging(LOG_VERBOSE, "Send a TESTUNITREADY with CMDSN == EXPCMDSN. should work again");
|
||||
TESTUNITREADY(sd,
|
||||
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
logging(LOG_VERBOSE, "Send a TESTUNITREADY with CMDSN == EXPCMDSN. should work again");
|
||||
TESTUNITREADY(sd,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
|
||||
@@ -29,63 +29,63 @@ static int change_cmdsn;
|
||||
|
||||
static int my_iscsi_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
|
||||
{
|
||||
switch (change_cmdsn) {
|
||||
case 1:
|
||||
/* change the cmdsn so it becomes too big */
|
||||
scsi_set_uint32(&pdu->outdata.data[24], iscsi->expcmdsn - 1);
|
||||
/* fudge the cmdsn value back to where it should be if this
|
||||
* pdu is ignored.
|
||||
*/
|
||||
iscsi->cmdsn = iscsi->expcmdsn;
|
||||
break;
|
||||
}
|
||||
switch (change_cmdsn) {
|
||||
case 1:
|
||||
/* change the cmdsn so it becomes too big */
|
||||
scsi_set_uint32(&pdu->outdata.data[24], iscsi->expcmdsn - 1);
|
||||
/* fudge the cmdsn value back to where it should be if this
|
||||
* pdu is ignored.
|
||||
*/
|
||||
iscsi->cmdsn = iscsi->expcmdsn;
|
||||
break;
|
||||
}
|
||||
|
||||
change_cmdsn = 0;
|
||||
return 0;
|
||||
change_cmdsn = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_iscsi_cmdsn_toolow(void)
|
||||
{
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test sending invalid iSCSI CMDSN");
|
||||
logging(LOG_VERBOSE, "CMDSN MUST be in the range EXPCMDSN and MAXCMDSN");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test sending invalid iSCSI CMDSN");
|
||||
logging(LOG_VERBOSE, "CMDSN MUST be in the range EXPCMDSN and MAXCMDSN");
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "RFC3720:3.2.2.1 CMDSN < EXPCMDSN must be silently ignored by the target");
|
||||
logging(LOG_VERBOSE, "Send a TESTUNITREADY with CMDSN == EXPCMDSN-1. Should be ignored by the target.");
|
||||
logging(LOG_VERBOSE, "RFC3720:3.2.2.1 CMDSN < EXPCMDSN must be silently ignored by the target");
|
||||
logging(LOG_VERBOSE, "Send a TESTUNITREADY with CMDSN == EXPCMDSN-1. Should be ignored by the target.");
|
||||
|
||||
sd->iscsi_ctx->use_immediate_data = ISCSI_IMMEDIATE_DATA_NO;
|
||||
sd->iscsi_ctx->target_max_recv_data_segment_length = block_size;
|
||||
local_iscsi_queue_pdu = my_iscsi_queue_pdu;
|
||||
change_cmdsn = 1;
|
||||
/* we don't want autoreconnect since some targets will incorrectly
|
||||
* drop the connection on this condition.
|
||||
*/
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
iscsi_set_timeout(sd->iscsi_ctx, 3);
|
||||
sd->iscsi_ctx->use_immediate_data = ISCSI_IMMEDIATE_DATA_NO;
|
||||
sd->iscsi_ctx->target_max_recv_data_segment_length = block_size;
|
||||
local_iscsi_queue_pdu = my_iscsi_queue_pdu;
|
||||
change_cmdsn = 1;
|
||||
/* we don't want autoreconnect since some targets will incorrectly
|
||||
* drop the connection on this condition.
|
||||
*/
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
iscsi_set_timeout(sd->iscsi_ctx, 3);
|
||||
|
||||
ret = testunitready(sd,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, -1);
|
||||
if (ret == -1) {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] We did not receive a reply");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[FAILURE] We got a response from the target but SMDSN was outside of the window.");
|
||||
}
|
||||
ret = testunitready(sd,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, -1);
|
||||
if (ret == -1) {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] We did not receive a reply");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[FAILURE] We got a response from the target but SMDSN was outside of the window.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
logging(LOG_VERBOSE, "Send a TESTUNITREADY with CMDSN == EXPCMDSN. should work again");
|
||||
TESTUNITREADY(sd,
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
logging(LOG_VERBOSE, "Send a TESTUNITREADY with CMDSN == EXPCMDSN. should work again");
|
||||
TESTUNITREADY(sd,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
|
||||
@@ -29,142 +29,142 @@ static int change_datasn;
|
||||
|
||||
static int my_iscsi_queue_pdu(struct iscsi_context *iscsi _U_, struct iscsi_pdu *pdu _U_)
|
||||
{
|
||||
uint32_t datasn;
|
||||
uint32_t datasn;
|
||||
|
||||
if (pdu->outdata.data[0] != ISCSI_PDU_DATA_OUT) {
|
||||
return 0;
|
||||
}
|
||||
switch (change_datasn) {
|
||||
case 1:
|
||||
/* change DataSN to 0 */
|
||||
scsi_set_uint32(&pdu->outdata.data[36], 0);
|
||||
break;
|
||||
case 2:
|
||||
/* change DataSN to 27 */
|
||||
scsi_set_uint32(&pdu->outdata.data[36], 27);
|
||||
break;
|
||||
case 3:
|
||||
/* change DataSN to -1 */
|
||||
scsi_set_uint32(&pdu->outdata.data[36], -1);
|
||||
break;
|
||||
case 4:
|
||||
/* change DataSN from (0,1) to (1,0) */
|
||||
datasn = scsi_get_uint32(&pdu->outdata.data[36]);
|
||||
scsi_set_uint32(&pdu->outdata.data[36], 1 - datasn);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
if (pdu->outdata.data[0] != ISCSI_PDU_DATA_OUT) {
|
||||
return 0;
|
||||
}
|
||||
switch (change_datasn) {
|
||||
case 1:
|
||||
/* change DataSN to 0 */
|
||||
scsi_set_uint32(&pdu->outdata.data[36], 0);
|
||||
break;
|
||||
case 2:
|
||||
/* change DataSN to 27 */
|
||||
scsi_set_uint32(&pdu->outdata.data[36], 27);
|
||||
break;
|
||||
case 3:
|
||||
/* change DataSN to -1 */
|
||||
scsi_set_uint32(&pdu->outdata.data[36], -1);
|
||||
break;
|
||||
case 4:
|
||||
/* change DataSN from (0,1) to (1,0) */
|
||||
datasn = scsi_get_uint32(&pdu->outdata.data[36]);
|
||||
scsi_set_uint32(&pdu->outdata.data[36], 1 - datasn);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_iscsi_datasn_invalid(void)
|
||||
{
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_DATALOSS;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test sending invalid iSCSI DataSN");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test sending invalid iSCSI DataSN");
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Send two Data-Out PDU's with DataSN==0. Should fail.");
|
||||
change_datasn = 1;
|
||||
logging(LOG_VERBOSE, "Send two Data-Out PDU's with DataSN==0. Should fail.");
|
||||
change_datasn = 1;
|
||||
|
||||
sd->iscsi_ctx->use_immediate_data = ISCSI_IMMEDIATE_DATA_NO;
|
||||
sd->iscsi_ctx->target_max_recv_data_segment_length = block_size;
|
||||
local_iscsi_queue_pdu = my_iscsi_queue_pdu;
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
iscsi_set_timeout(sd->iscsi_ctx, 3);
|
||||
sd->iscsi_ctx->use_immediate_data = ISCSI_IMMEDIATE_DATA_NO;
|
||||
sd->iscsi_ctx->target_max_recv_data_segment_length = block_size;
|
||||
local_iscsi_queue_pdu = my_iscsi_queue_pdu;
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
iscsi_set_timeout(sd->iscsi_ctx, 3);
|
||||
|
||||
memset(scratch, 0xa6, 2 * block_size);
|
||||
memset(scratch, 0xa6, 2 * block_size);
|
||||
|
||||
ret = write10(sd, 100, 2 * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] WRITE10 is not implemented.");
|
||||
CU_PASS("WRITE10 is not implemented.");
|
||||
local_iscsi_queue_pdu = NULL;
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_NOT_EQUAL(ret, 0);
|
||||
ret = write10(sd, 100, 2 * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] WRITE10 is not implemented.");
|
||||
CU_PASS("WRITE10 is not implemented.");
|
||||
local_iscsi_queue_pdu = NULL;
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_NOT_EQUAL(ret, 0);
|
||||
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Send Data-Out PDU with DataSN==27. Should fail");
|
||||
change_datasn = 2;
|
||||
logging(LOG_VERBOSE, "Send Data-Out PDU with DataSN==27. Should fail");
|
||||
change_datasn = 2;
|
||||
|
||||
sd->iscsi_ctx->use_immediate_data = ISCSI_IMMEDIATE_DATA_NO;
|
||||
sd->iscsi_ctx->target_max_recv_data_segment_length = block_size;
|
||||
local_iscsi_queue_pdu = my_iscsi_queue_pdu;
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
iscsi_set_timeout(sd->iscsi_ctx, 3);
|
||||
sd->iscsi_ctx->use_immediate_data = ISCSI_IMMEDIATE_DATA_NO;
|
||||
sd->iscsi_ctx->target_max_recv_data_segment_length = block_size;
|
||||
local_iscsi_queue_pdu = my_iscsi_queue_pdu;
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
iscsi_set_timeout(sd->iscsi_ctx, 3);
|
||||
|
||||
ret = write10(sd, 100, block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] WRITE10 is not implemented.");
|
||||
CU_PASS("WRITE10 is not implemented.");
|
||||
local_iscsi_queue_pdu = NULL;
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_NOT_EQUAL(ret, 0);
|
||||
ret = write10(sd, 100, block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] WRITE10 is not implemented.");
|
||||
CU_PASS("WRITE10 is not implemented.");
|
||||
local_iscsi_queue_pdu = NULL;
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_NOT_EQUAL(ret, 0);
|
||||
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Send Data-Out PDU with DataSN==-1. Should fail");
|
||||
change_datasn = 3;
|
||||
logging(LOG_VERBOSE, "Send Data-Out PDU with DataSN==-1. Should fail");
|
||||
change_datasn = 3;
|
||||
|
||||
sd->iscsi_ctx->use_immediate_data = ISCSI_IMMEDIATE_DATA_NO;
|
||||
sd->iscsi_ctx->target_max_recv_data_segment_length = block_size;
|
||||
local_iscsi_queue_pdu = my_iscsi_queue_pdu;
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
iscsi_set_timeout(sd->iscsi_ctx, 3);
|
||||
sd->iscsi_ctx->use_immediate_data = ISCSI_IMMEDIATE_DATA_NO;
|
||||
sd->iscsi_ctx->target_max_recv_data_segment_length = block_size;
|
||||
local_iscsi_queue_pdu = my_iscsi_queue_pdu;
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
iscsi_set_timeout(sd->iscsi_ctx, 3);
|
||||
|
||||
ret = write10(sd, 100, block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] WRITE10 is not implemented.");
|
||||
CU_PASS("WRITE10 is not implemented.");
|
||||
local_iscsi_queue_pdu = NULL;
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_NOT_EQUAL(ret, 0);
|
||||
ret = write10(sd, 100, block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] WRITE10 is not implemented.");
|
||||
CU_PASS("WRITE10 is not implemented.");
|
||||
local_iscsi_queue_pdu = NULL;
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_NOT_EQUAL(ret, 0);
|
||||
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Send Data-Out PDU's in reverse order (DataSN == 1,0). Should fail");
|
||||
change_datasn = 4;
|
||||
logging(LOG_VERBOSE, "Send Data-Out PDU's in reverse order (DataSN == 1,0). Should fail");
|
||||
change_datasn = 4;
|
||||
|
||||
sd->iscsi_ctx->use_immediate_data = ISCSI_IMMEDIATE_DATA_NO;
|
||||
sd->iscsi_ctx->target_max_recv_data_segment_length = block_size;
|
||||
local_iscsi_queue_pdu = my_iscsi_queue_pdu;
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
iscsi_set_timeout(sd->iscsi_ctx, 3);
|
||||
sd->iscsi_ctx->use_immediate_data = ISCSI_IMMEDIATE_DATA_NO;
|
||||
sd->iscsi_ctx->target_max_recv_data_segment_length = block_size;
|
||||
local_iscsi_queue_pdu = my_iscsi_queue_pdu;
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
iscsi_set_timeout(sd->iscsi_ctx, 3);
|
||||
|
||||
ret = write10(sd, 100, 2 * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] WRITE10 is not implemented.");
|
||||
CU_PASS("WRITE10 is not implemented.");
|
||||
local_iscsi_queue_pdu = NULL;
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_NOT_EQUAL(ret, 0);
|
||||
ret = write10(sd, 100, 2 * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] WRITE10 is not implemented.");
|
||||
CU_PASS("WRITE10 is not implemented.");
|
||||
local_iscsi_queue_pdu = NULL;
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_NOT_EQUAL(ret, 0);
|
||||
|
||||
local_iscsi_queue_pdu = NULL;
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
local_iscsi_queue_pdu = NULL;
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
}
|
||||
|
||||
@@ -28,48 +28,48 @@
|
||||
void
|
||||
test_mandatory_sbc(void)
|
||||
{
|
||||
int ret;
|
||||
//unsigned char buf[4096];
|
||||
//struct unmap_list list[1];
|
||||
int ret;
|
||||
//unsigned char buf[4096];
|
||||
//struct unmap_list list[1];
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test support for all mandatory opcodes on SBC devices");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test support for all mandatory opcodes on SBC devices");
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
logging(LOG_VERBOSE, "Test INQUIRY.");
|
||||
ret = inquiry(sd, NULL, 0, 0, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "Test INQUIRY.");
|
||||
ret = inquiry(sd, NULL, 0, 0, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Test READCAPACITY10.");
|
||||
ret = readcapacity10(sd, NULL, 0, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "Test READCAPACITY10.");
|
||||
ret = readcapacity10(sd, NULL, 0, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
if (sbc3_support) {
|
||||
logging(LOG_VERBOSE, "Test READCAPACITY16. The device claims SBC-3 support.");
|
||||
ret = readcapacity16(sd, NULL, 15,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
if (sbc3_support) {
|
||||
logging(LOG_VERBOSE, "Test READCAPACITY16. The device claims SBC-3 support.");
|
||||
ret = readcapacity16(sd, NULL, 15,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ10.");
|
||||
ret = read10(sd, NULL, 0, block_size, block_size,
|
||||
0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "Test READ10.");
|
||||
ret = read10(sd, NULL, 0, block_size, block_size,
|
||||
0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
if (sbc3_support) {
|
||||
logging(LOG_VERBOSE, "Test READ16. the device claims SBC-3 support.");
|
||||
ret = read16(sd, NULL, 0, block_size, block_size,
|
||||
0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
if (sbc3_support) {
|
||||
logging(LOG_VERBOSE, "Test READ16. the device claims SBC-3 support.");
|
||||
ret = read16(sd, NULL, 0, block_size, block_size,
|
||||
0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test TESTUNITREADY.");
|
||||
ret = testunitready(sd,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "Test TESTUNITREADY.");
|
||||
ret = testunitready(sd,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
|
||||
@@ -28,39 +28,39 @@
|
||||
void
|
||||
test_modesense6_all_pages(void)
|
||||
{
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_task *ms_task = NULL;
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_task *ms_task = NULL;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of MODESENSE6 AllPages");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of MODESENSE6 AllPages");
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Send MODESENSE6 command to fetch AllPages");
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
logging(LOG_VERBOSE, "Send MODESENSE6 command to fetch AllPages");
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "[SUCCESS] All Pages fetched.");
|
||||
logging(LOG_VERBOSE, "[SUCCESS] All Pages fetched.");
|
||||
|
||||
logging(LOG_VERBOSE, "Try to unmarshall the DATA-IN buffer.");
|
||||
ms = scsi_datain_unmarshall(ms_task);
|
||||
if (ms == NULL) {
|
||||
logging(LOG_VERBOSE, "[FAILED] failed to unmarshall mode sense "
|
||||
"datain buffer");
|
||||
CU_FAIL("[FAILED] Failed to unmarshall the data-in buffer.");
|
||||
scsi_free_scsi_task(ms_task);
|
||||
return;
|
||||
}
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Unmarshalling successful.");
|
||||
logging(LOG_VERBOSE, "Try to unmarshall the DATA-IN buffer.");
|
||||
ms = scsi_datain_unmarshall(ms_task);
|
||||
if (ms == NULL) {
|
||||
logging(LOG_VERBOSE, "[FAILED] failed to unmarshall mode sense "
|
||||
"datain buffer");
|
||||
CU_FAIL("[FAILED] Failed to unmarshall the data-in buffer.");
|
||||
scsi_free_scsi_task(ms_task);
|
||||
return;
|
||||
}
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Unmarshalling successful.");
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that mode data length is >= 3");
|
||||
if (ms->mode_data_length >= 3) {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode data length is >= 3");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[FAILED] Mode data length is < 3");
|
||||
}
|
||||
CU_ASSERT_TRUE(ms->mode_data_length >= 3);
|
||||
logging(LOG_VERBOSE, "Verify that mode data length is >= 3");
|
||||
if (ms->mode_data_length >= 3) {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode data length is >= 3");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[FAILED] Mode data length is < 3");
|
||||
}
|
||||
CU_ASSERT_TRUE(ms->mode_data_length >= 3);
|
||||
|
||||
|
||||
scsi_free_scsi_task(ms_task);
|
||||
scsi_free_scsi_task(ms_task);
|
||||
}
|
||||
|
||||
@@ -28,213 +28,213 @@
|
||||
void
|
||||
test_modesense6_control(void)
|
||||
{
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_mode_page *ap_page;
|
||||
struct scsi_mode_page *ct_page;
|
||||
struct scsi_task *ap_task = NULL;
|
||||
struct scsi_task *ct_task = NULL;
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_mode_page *ap_page;
|
||||
struct scsi_mode_page *ct_page;
|
||||
struct scsi_task *ap_task = NULL;
|
||||
struct scsi_task *ct_task = NULL;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of MODESENSE6 CONTROL page");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of MODESENSE6 CONTROL page");
|
||||
|
||||
logging(LOG_VERBOSE, "Fetch the CONTROL page via AllPages");
|
||||
logging(LOG_VERBOSE, "Send MODESENSE6 command to fetch AllPages");
|
||||
MODESENSE6(sd, &ap_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
logging(LOG_VERBOSE, "Fetch the CONTROL page via AllPages");
|
||||
logging(LOG_VERBOSE, "Send MODESENSE6 command to fetch AllPages");
|
||||
MODESENSE6(sd, &ap_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "[SUCCESS] All Pages fetched.");
|
||||
logging(LOG_VERBOSE, "[SUCCESS] All Pages fetched.");
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try to unmarshall the DATA-IN buffer.");
|
||||
ms = scsi_datain_unmarshall(ap_task);
|
||||
if (ms == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] failed to unmarshall mode sense "
|
||||
"datain buffer");
|
||||
CU_FAIL("[FAILED] Failed to unmarshall the data-in buffer.");
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Unmarshalling successful.");
|
||||
logging(LOG_VERBOSE, "Try to unmarshall the DATA-IN buffer.");
|
||||
ms = scsi_datain_unmarshall(ap_task);
|
||||
if (ms == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] failed to unmarshall mode sense "
|
||||
"datain buffer");
|
||||
CU_FAIL("[FAILED] Failed to unmarshall the data-in buffer.");
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Unmarshalling successful.");
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that mode data length is >= 3");
|
||||
if (ms->mode_data_length >= 3) {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode data length is >= 3");
|
||||
} else {
|
||||
logging(LOG_NORMAL, "[FAILED] Mode data length is < 3");
|
||||
}
|
||||
CU_ASSERT_TRUE(ms->mode_data_length >= 3);
|
||||
logging(LOG_VERBOSE, "Verify that mode data length is >= 3");
|
||||
if (ms->mode_data_length >= 3) {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode data length is >= 3");
|
||||
} else {
|
||||
logging(LOG_NORMAL, "[FAILED] Mode data length is < 3");
|
||||
}
|
||||
CU_ASSERT_TRUE(ms->mode_data_length >= 3);
|
||||
|
||||
for (ap_page = ms->pages; ap_page; ap_page = ap_page->next) {
|
||||
if (ap_page->page_code == SCSI_MODEPAGE_CONTROL &&
|
||||
ap_page->spf == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(ap_page == NULL) {
|
||||
logging(LOG_NORMAL, "[WARNING] CONTROL page was not returned "
|
||||
"from AllPages. All devices SHOULD implement this "
|
||||
"page.");
|
||||
}
|
||||
for (ap_page = ms->pages; ap_page; ap_page = ap_page->next) {
|
||||
if (ap_page->page_code == SCSI_MODEPAGE_CONTROL &&
|
||||
ap_page->spf == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(ap_page == NULL) {
|
||||
logging(LOG_NORMAL, "[WARNING] CONTROL page was not returned "
|
||||
"from AllPages. All devices SHOULD implement this "
|
||||
"page.");
|
||||
}
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Fetch the CONTROL page directly");
|
||||
logging(LOG_VERBOSE, "Send MODESENSE6 command to fetch CONTROL");
|
||||
MODESENSE6(sd, &ct_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
logging(LOG_VERBOSE, "Fetch the CONTROL page directly");
|
||||
logging(LOG_VERBOSE, "Send MODESENSE6 command to fetch CONTROL");
|
||||
MODESENSE6(sd, &ct_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODEPAGE_CONTROL, 0, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "[SUCCESS] CONTROL page fetched.");
|
||||
logging(LOG_VERBOSE, "[SUCCESS] CONTROL page fetched.");
|
||||
|
||||
logging(LOG_VERBOSE, "Try to unmarshall the DATA-IN buffer.");
|
||||
ms = scsi_datain_unmarshall(ct_task);
|
||||
if (ms == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] failed to unmarshall mode sense "
|
||||
"datain buffer");
|
||||
CU_FAIL("[FAILED] Failed to unmarshall the data-in buffer.");
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Unmarshalling successful.");
|
||||
logging(LOG_VERBOSE, "Try to unmarshall the DATA-IN buffer.");
|
||||
ms = scsi_datain_unmarshall(ct_task);
|
||||
if (ms == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] failed to unmarshall mode sense "
|
||||
"datain buffer");
|
||||
CU_FAIL("[FAILED] Failed to unmarshall the data-in buffer.");
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Unmarshalling successful.");
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that mode data length is >= 3");
|
||||
if (ms->mode_data_length >= 3) {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode data length is >= 3");
|
||||
} else {
|
||||
logging(LOG_NORMAL, "[FAILED] Mode data length is < 3");
|
||||
}
|
||||
CU_ASSERT_TRUE(ms->mode_data_length >= 3);
|
||||
logging(LOG_VERBOSE, "Verify that mode data length is >= 3");
|
||||
if (ms->mode_data_length >= 3) {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode data length is >= 3");
|
||||
} else {
|
||||
logging(LOG_NORMAL, "[FAILED] Mode data length is < 3");
|
||||
}
|
||||
CU_ASSERT_TRUE(ms->mode_data_length >= 3);
|
||||
|
||||
for (ct_page = ms->pages; ct_page; ct_page = ct_page->next) {
|
||||
if (ct_page->page_code == SCSI_MODEPAGE_CONTROL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(ct_page == NULL) {
|
||||
logging(LOG_NORMAL, "[WARNING] CONTROL page was not returned."
|
||||
"All devices SHOULD implement this page.");
|
||||
}
|
||||
for (ct_page = ms->pages; ct_page; ct_page = ct_page->next) {
|
||||
if (ct_page->page_code == SCSI_MODEPAGE_CONTROL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(ct_page == NULL) {
|
||||
logging(LOG_NORMAL, "[WARNING] CONTROL page was not returned."
|
||||
"All devices SHOULD implement this page.");
|
||||
}
|
||||
|
||||
if (ap_page == NULL && ct_page != NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] CONTROL page was not returned "
|
||||
"from AllPages.");
|
||||
CU_FAIL("[FAILED] CONTROL page is missing from AllPages");
|
||||
goto finished;
|
||||
}
|
||||
if (ap_page == NULL && ct_page != NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] CONTROL page was not returned "
|
||||
"from AllPages.");
|
||||
CU_FAIL("[FAILED] CONTROL page is missing from AllPages");
|
||||
goto finished;
|
||||
}
|
||||
|
||||
if (ap_page != NULL && ct_page == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] CONTROL page is only available "
|
||||
"from AllPages but not directly.");
|
||||
CU_FAIL("[FAILED] CONTROL page is missing");
|
||||
goto finished;
|
||||
}
|
||||
if (ap_page != NULL && ct_page == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] CONTROL page is only available "
|
||||
"from AllPages but not directly.");
|
||||
CU_FAIL("[FAILED] CONTROL page is missing");
|
||||
goto finished;
|
||||
}
|
||||
|
||||
if (ct_page == NULL) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] CONTROL page is not "
|
||||
"implemented.");
|
||||
CU_PASS("CONTROL page is not implemented.");
|
||||
goto finished;
|
||||
}
|
||||
if (ct_page == NULL) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] CONTROL page is not "
|
||||
"implemented.");
|
||||
CU_PASS("CONTROL page is not implemented.");
|
||||
goto finished;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the two pages are identical.");
|
||||
logging(LOG_VERBOSE, "Verify that the two pages are identical.");
|
||||
|
||||
logging(LOG_VERBOSE, "Check TST field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.tst, ap_page->control.tst);
|
||||
logging(LOG_VERBOSE, "Check TMF_ONLY field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.tmf_only, ap_page->control.tmf_only);
|
||||
logging(LOG_VERBOSE, "Check dpicz field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.dpicz, ap_page->control.dpicz);
|
||||
logging(LOG_VERBOSE, "Check d_sense field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.d_sense, ap_page->control.d_sense);
|
||||
logging(LOG_VERBOSE, "Check gltsd field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.gltsd, ap_page->control.gltsd);
|
||||
logging(LOG_VERBOSE, "Check rlec field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.rlec, ap_page->control.rlec);
|
||||
logging(LOG_VERBOSE, "Check queue_algorithm_modifier field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.queue_algorithm_modifier,
|
||||
ap_page->control.queue_algorithm_modifier);
|
||||
logging(LOG_VERBOSE, "Check nuar field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.nuar, ap_page->control.nuar);
|
||||
logging(LOG_VERBOSE, "Check qerr field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.qerr, ap_page->control.qerr);
|
||||
logging(LOG_VERBOSE, "Check vs field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.vs, ap_page->control.vs);
|
||||
logging(LOG_VERBOSE, "Check rac field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.rac, ap_page->control.rac);
|
||||
logging(LOG_VERBOSE, "Check ua_intlck_ctrl field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.ua_intlck_ctrl,
|
||||
ap_page->control.ua_intlck_ctrl);
|
||||
logging(LOG_VERBOSE, "Check swp field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.swp, ap_page->control.swp);
|
||||
logging(LOG_VERBOSE, "Check ato field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.ato, ap_page->control.ato);
|
||||
logging(LOG_VERBOSE, "Check tas field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.tas, ap_page->control.tas);
|
||||
logging(LOG_VERBOSE, "Check atmpe field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.atmpe, ap_page->control.atmpe);
|
||||
logging(LOG_VERBOSE, "Check rwwp field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.rwwp, ap_page->control.rwwp);
|
||||
logging(LOG_VERBOSE, "Check autoload_mode field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.autoload_mode,
|
||||
ap_page->control.autoload_mode);
|
||||
logging(LOG_VERBOSE, "Check busy_timeout_period field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.busy_timeout_period,
|
||||
ap_page->control.busy_timeout_period);
|
||||
logging(LOG_VERBOSE, "Check extended_selftest_completion_time field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.extended_selftest_completion_time,
|
||||
ap_page->control.extended_selftest_completion_time);
|
||||
logging(LOG_VERBOSE, "Check TST field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.tst, ap_page->control.tst);
|
||||
logging(LOG_VERBOSE, "Check TMF_ONLY field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.tmf_only, ap_page->control.tmf_only);
|
||||
logging(LOG_VERBOSE, "Check dpicz field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.dpicz, ap_page->control.dpicz);
|
||||
logging(LOG_VERBOSE, "Check d_sense field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.d_sense, ap_page->control.d_sense);
|
||||
logging(LOG_VERBOSE, "Check gltsd field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.gltsd, ap_page->control.gltsd);
|
||||
logging(LOG_VERBOSE, "Check rlec field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.rlec, ap_page->control.rlec);
|
||||
logging(LOG_VERBOSE, "Check queue_algorithm_modifier field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.queue_algorithm_modifier,
|
||||
ap_page->control.queue_algorithm_modifier);
|
||||
logging(LOG_VERBOSE, "Check nuar field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.nuar, ap_page->control.nuar);
|
||||
logging(LOG_VERBOSE, "Check qerr field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.qerr, ap_page->control.qerr);
|
||||
logging(LOG_VERBOSE, "Check vs field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.vs, ap_page->control.vs);
|
||||
logging(LOG_VERBOSE, "Check rac field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.rac, ap_page->control.rac);
|
||||
logging(LOG_VERBOSE, "Check ua_intlck_ctrl field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.ua_intlck_ctrl,
|
||||
ap_page->control.ua_intlck_ctrl);
|
||||
logging(LOG_VERBOSE, "Check swp field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.swp, ap_page->control.swp);
|
||||
logging(LOG_VERBOSE, "Check ato field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.ato, ap_page->control.ato);
|
||||
logging(LOG_VERBOSE, "Check tas field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.tas, ap_page->control.tas);
|
||||
logging(LOG_VERBOSE, "Check atmpe field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.atmpe, ap_page->control.atmpe);
|
||||
logging(LOG_VERBOSE, "Check rwwp field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.rwwp, ap_page->control.rwwp);
|
||||
logging(LOG_VERBOSE, "Check autoload_mode field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.autoload_mode,
|
||||
ap_page->control.autoload_mode);
|
||||
logging(LOG_VERBOSE, "Check busy_timeout_period field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.busy_timeout_period,
|
||||
ap_page->control.busy_timeout_period);
|
||||
logging(LOG_VERBOSE, "Check extended_selftest_completion_time field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.extended_selftest_completion_time,
|
||||
ap_page->control.extended_selftest_completion_time);
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the values are sane.");
|
||||
logging(LOG_VERBOSE, "Check that TST is 0 or 1.");
|
||||
if (ct_page->control.tst > 1) {
|
||||
logging(LOG_NORMAL, "[FAILED] TST value is invalid. Must be "
|
||||
"0, 1 but was %d", ct_page->control.tst);
|
||||
CU_FAIL("[FAILED] TST is invalid.");
|
||||
}
|
||||
logging(LOG_VERBOSE, "Check that QUEUE_ALGORITHM_MODIFIER is "
|
||||
"0, 1 or >7");
|
||||
if (ct_page->control.queue_algorithm_modifier > 1 &&
|
||||
ct_page->control.queue_algorithm_modifier < 8) {
|
||||
logging(LOG_NORMAL, "[FAILED] QUEUE_ALGORITHM_MODIFIER value "
|
||||
"is invalid. Must be 0, 1 or >7 but was %d",
|
||||
ct_page->control.queue_algorithm_modifier);
|
||||
CU_FAIL("[FAILED] QUEUE_ALGORITHM_MODIFIER is invalid.");
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify that the values are sane.");
|
||||
logging(LOG_VERBOSE, "Check that TST is 0 or 1.");
|
||||
if (ct_page->control.tst > 1) {
|
||||
logging(LOG_NORMAL, "[FAILED] TST value is invalid. Must be "
|
||||
"0, 1 but was %d", ct_page->control.tst);
|
||||
CU_FAIL("[FAILED] TST is invalid.");
|
||||
}
|
||||
logging(LOG_VERBOSE, "Check that QUEUE_ALGORITHM_MODIFIER is "
|
||||
"0, 1 or >7");
|
||||
if (ct_page->control.queue_algorithm_modifier > 1 &&
|
||||
ct_page->control.queue_algorithm_modifier < 8) {
|
||||
logging(LOG_NORMAL, "[FAILED] QUEUE_ALGORITHM_MODIFIER value "
|
||||
"is invalid. Must be 0, 1 or >7 but was %d",
|
||||
ct_page->control.queue_algorithm_modifier);
|
||||
CU_FAIL("[FAILED] QUEUE_ALGORITHM_MODIFIER is invalid.");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Check that QERR is not 2");
|
||||
if (ct_page->control.qerr == 2) {
|
||||
logging(LOG_NORMAL, "[FAILED] QERR value "
|
||||
"is invalid. Can not be 2");
|
||||
CU_FAIL("[FAILED] QERR is invalid.");
|
||||
}
|
||||
logging(LOG_VERBOSE, "Check that QERR is not 2");
|
||||
if (ct_page->control.qerr == 2) {
|
||||
logging(LOG_NORMAL, "[FAILED] QERR value "
|
||||
"is invalid. Can not be 2");
|
||||
CU_FAIL("[FAILED] QERR is invalid.");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Check that UA_INTLCK_CTRL is not 1");
|
||||
if (ct_page->control.ua_intlck_ctrl == 1) {
|
||||
logging(LOG_NORMAL, "[FAILED] UA_INTLCK_CTRL value "
|
||||
"is invalid. Can not be 1");
|
||||
CU_FAIL("[FAILED] UA_INTLCK_CTRL is invalid.");
|
||||
}
|
||||
logging(LOG_VERBOSE, "Check that UA_INTLCK_CTRL is not 1");
|
||||
if (ct_page->control.ua_intlck_ctrl == 1) {
|
||||
logging(LOG_NORMAL, "[FAILED] UA_INTLCK_CTRL value "
|
||||
"is invalid. Can not be 1");
|
||||
CU_FAIL("[FAILED] UA_INTLCK_CTRL is invalid.");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Check that AUTOLOAD is 0, 1 or 2");
|
||||
if (ct_page->control.autoload_mode > 2) {
|
||||
logging(LOG_NORMAL, "[FAILED] AUTOLOAD value "
|
||||
"is invalid. Must be 0, 1 or 2 but was %d",
|
||||
ct_page->control.autoload_mode);
|
||||
CU_FAIL("[FAILED] AUTOLOAD is invalid.");
|
||||
}
|
||||
logging(LOG_VERBOSE, "Check that AUTOLOAD is 0, 1 or 2");
|
||||
if (ct_page->control.autoload_mode > 2) {
|
||||
logging(LOG_NORMAL, "[FAILED] AUTOLOAD value "
|
||||
"is invalid. Must be 0, 1 or 2 but was %d",
|
||||
ct_page->control.autoload_mode);
|
||||
CU_FAIL("[FAILED] AUTOLOAD is invalid.");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Check that BUSY_TIMEOUT_PERIOD is specified");
|
||||
if (ct_page->control.busy_timeout_period == 0) {
|
||||
logging(LOG_NORMAL, "[WARNING] BUSY_TIMEOUT_PERIOD is "
|
||||
"undefined.");
|
||||
}
|
||||
logging(LOG_VERBOSE, "Check that BUSY_TIMEOUT_PERIOD is specified");
|
||||
if (ct_page->control.busy_timeout_period == 0) {
|
||||
logging(LOG_NORMAL, "[WARNING] BUSY_TIMEOUT_PERIOD is "
|
||||
"undefined.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
finished:
|
||||
if (ap_task != NULL) {
|
||||
scsi_free_scsi_task(ap_task);
|
||||
}
|
||||
if (ct_task != NULL) {
|
||||
scsi_free_scsi_task(ct_task);
|
||||
}
|
||||
if (ap_task != NULL) {
|
||||
scsi_free_scsi_task(ap_task);
|
||||
}
|
||||
if (ct_task != NULL) {
|
||||
scsi_free_scsi_task(ct_task);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,86 +29,86 @@
|
||||
void
|
||||
test_modesense6_control_d_sense(void)
|
||||
{
|
||||
struct scsi_task *ms_task = NULL;
|
||||
struct scsi_task *r16_task = NULL;
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_mode_page *page;
|
||||
int ret;
|
||||
struct scsi_task *ms_task = NULL;
|
||||
struct scsi_task *r16_task = NULL;
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_mode_page *page;
|
||||
int ret;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of MODESENSE6 CONTROL D_SENSE flag");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of MODESENSE6 CONTROL D_SENSE flag");
|
||||
|
||||
logging(LOG_VERBOSE, "Read the CONTROL page from the device");
|
||||
ret = modesense6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODEPAGE_CONTROL, 0, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (ret != 0) {
|
||||
logging(LOG_NORMAL,"[WARNING] Could not read "
|
||||
"BlockDeviceCharacteristics.");
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "[SUCCESS] CONTROL page fetched.");
|
||||
logging(LOG_VERBOSE, "Read the CONTROL page from the device");
|
||||
ret = modesense6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODEPAGE_CONTROL, 0, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (ret != 0) {
|
||||
logging(LOG_NORMAL,"[WARNING] Could not read "
|
||||
"BlockDeviceCharacteristics.");
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "[SUCCESS] CONTROL page fetched.");
|
||||
|
||||
logging(LOG_VERBOSE, "Try to unmarshall the DATA-IN buffer.");
|
||||
ms = scsi_datain_unmarshall(ms_task);
|
||||
if (ms == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] failed to unmarshall mode sense "
|
||||
"datain buffer");
|
||||
CU_FAIL("[FAILED] Failed to unmarshall the data-in buffer.");
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Unmarshalling successful.");
|
||||
for (page = ms->pages; page; page = page->next) {
|
||||
if (page->page_code == SCSI_MODEPAGE_CONTROL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(page == NULL) {
|
||||
logging(LOG_NORMAL, "[WARNING] CONTROL page was not returned."
|
||||
"All devices SHOULD implement this page.");
|
||||
CU_PASS("[SKIPPED] CONTROL page not reported");
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Send a READ16 that will fail so we can check "
|
||||
"the type of sense data returned");
|
||||
READ16(sd, &r16_task, 0xffffffffffffffffLL, block_size, block_size, 0,
|
||||
logging(LOG_VERBOSE, "Try to unmarshall the DATA-IN buffer.");
|
||||
ms = scsi_datain_unmarshall(ms_task);
|
||||
if (ms == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] failed to unmarshall mode sense "
|
||||
"datain buffer");
|
||||
CU_FAIL("[FAILED] Failed to unmarshall the data-in buffer.");
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Unmarshalling successful.");
|
||||
for (page = ms->pages; page; page = page->next) {
|
||||
if (page->page_code == SCSI_MODEPAGE_CONTROL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(page == NULL) {
|
||||
logging(LOG_NORMAL, "[WARNING] CONTROL page was not returned."
|
||||
"All devices SHOULD implement this page.");
|
||||
CU_PASS("[SKIPPED] CONTROL page not reported");
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Send a READ16 that will fail so we can check "
|
||||
"the type of sense data returned");
|
||||
READ16(sd, &r16_task, 0xffffffffffffffffLL, block_size, block_size, 0,
|
||||
0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
|
||||
if (page->control.d_sense) {
|
||||
logging(LOG_VERBOSE, "D_SENSE is set, verify that sense format "
|
||||
"is descriptor format");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "D_SENSE is clear, verify that sense format "
|
||||
"is fixed format");
|
||||
}
|
||||
switch (r16_task->sense.error_type) {
|
||||
case SCSI_SENSE_DESCRIPTOR_CURRENT:
|
||||
case SCSI_SENSE_DESCRIPTOR_DEFERRED_ERRORS:
|
||||
if (!page->control.d_sense) {
|
||||
logging(LOG_NORMAL, "[FAILED] D_SENSE is set but "
|
||||
"returned sense is not descriptor format");
|
||||
CU_FAIL("[FAILED] Wrong type of sense format returned");
|
||||
goto finished;
|
||||
}
|
||||
break;
|
||||
case SCSI_SENSE_FIXED_CURRENT:
|
||||
case SCSI_SENSE_FIXED_DEFERRED_ERRORS:
|
||||
if (page->control.d_sense) {
|
||||
logging(LOG_NORMAL, "[FAILED] D_SENSE is cleat but "
|
||||
"returned sense is not fixed format");
|
||||
CU_FAIL("[FAILED] Wrong type of sense format returned");
|
||||
goto finished;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (page->control.d_sense) {
|
||||
logging(LOG_VERBOSE, "D_SENSE is set, verify that sense format "
|
||||
"is descriptor format");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "D_SENSE is clear, verify that sense format "
|
||||
"is fixed format");
|
||||
}
|
||||
switch (r16_task->sense.error_type) {
|
||||
case SCSI_SENSE_DESCRIPTOR_CURRENT:
|
||||
case SCSI_SENSE_DESCRIPTOR_DEFERRED_ERRORS:
|
||||
if (!page->control.d_sense) {
|
||||
logging(LOG_NORMAL, "[FAILED] D_SENSE is set but "
|
||||
"returned sense is not descriptor format");
|
||||
CU_FAIL("[FAILED] Wrong type of sense format returned");
|
||||
goto finished;
|
||||
}
|
||||
break;
|
||||
case SCSI_SENSE_FIXED_CURRENT:
|
||||
case SCSI_SENSE_FIXED_DEFERRED_ERRORS:
|
||||
if (page->control.d_sense) {
|
||||
logging(LOG_NORMAL, "[FAILED] D_SENSE is cleat but "
|
||||
"returned sense is not fixed format");
|
||||
CU_FAIL("[FAILED] Wrong type of sense format returned");
|
||||
goto finished;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
finished:
|
||||
if (ms_task != NULL) {
|
||||
scsi_free_scsi_task(ms_task);
|
||||
}
|
||||
if (r16_task != NULL) {
|
||||
scsi_free_scsi_task(r16_task);
|
||||
}
|
||||
if (ms_task != NULL) {
|
||||
scsi_free_scsi_task(ms_task);
|
||||
}
|
||||
if (r16_task != NULL) {
|
||||
scsi_free_scsi_task(r16_task);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,74 +29,74 @@
|
||||
void
|
||||
test_modesense6_control_swp(void)
|
||||
{
|
||||
struct scsi_task *ms_task = NULL;
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_mode_page *page;
|
||||
int ret;
|
||||
struct scsi_task *ms_task = NULL;
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_mode_page *page;
|
||||
int ret;
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of MODESENSE6 CONTROL SWP flag");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of MODESENSE6 CONTROL SWP flag");
|
||||
|
||||
logging(LOG_VERBOSE, "Set SWP to enable write protect");
|
||||
ret = set_swp(sd);
|
||||
if (ret == -2) {
|
||||
CU_PASS("[SKIPPED] Target does not support changing SWP");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret) {
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Set SWP to enable write protect");
|
||||
ret = set_swp(sd);
|
||||
if (ret == -2) {
|
||||
CU_PASS("[SKIPPED] Target does not support changing SWP");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret) {
|
||||
goto finished;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Read the CONTROL page back from the device");
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
logging(LOG_VERBOSE, "Read the CONTROL page back from the device");
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODEPAGE_CONTROL, 0, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "[SUCCESS] CONTROL page fetched.");
|
||||
logging(LOG_VERBOSE, "[SUCCESS] CONTROL page fetched.");
|
||||
|
||||
logging(LOG_VERBOSE, "Try to unmarshall the DATA-IN buffer.");
|
||||
ms = scsi_datain_unmarshall(ms_task);
|
||||
if (ms == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] failed to unmarshall mode sense "
|
||||
"datain buffer");
|
||||
CU_FAIL("[FAILED] Failed to unmarshall the data-in buffer.");
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Unmarshalling successful.");
|
||||
for (page = ms->pages; page; page = page->next) {
|
||||
if (page->page_code == SCSI_MODEPAGE_CONTROL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(page == NULL) {
|
||||
logging(LOG_NORMAL, "[WARNING] CONTROL page was not returned."
|
||||
"All devices SHOULD implement this page.");
|
||||
}
|
||||
logging(LOG_VERBOSE, "Try to unmarshall the DATA-IN buffer.");
|
||||
ms = scsi_datain_unmarshall(ms_task);
|
||||
if (ms == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] failed to unmarshall mode sense "
|
||||
"datain buffer");
|
||||
CU_FAIL("[FAILED] Failed to unmarshall the data-in buffer.");
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Unmarshalling successful.");
|
||||
for (page = ms->pages; page; page = page->next) {
|
||||
if (page->page_code == SCSI_MODEPAGE_CONTROL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(page == NULL) {
|
||||
logging(LOG_NORMAL, "[WARNING] CONTROL page was not returned."
|
||||
"All devices SHOULD implement this page.");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the SWP bit is set");
|
||||
if (page->control.swp == 0) {
|
||||
logging(LOG_NORMAL, "[FAILED] SWP bit is not set");
|
||||
CU_FAIL("[FAILED] SWP is not set");
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "[SUCCESS] SWP was set successfully");
|
||||
logging(LOG_VERBOSE, "Verify that the SWP bit is set");
|
||||
if (page->control.swp == 0) {
|
||||
logging(LOG_NORMAL, "[FAILED] SWP bit is not set");
|
||||
CU_FAIL("[FAILED] SWP is not set");
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "[SUCCESS] SWP was set successfully");
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Read a block from the now Read-Only device");
|
||||
READ10(sd, NULL, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Read a block from the now Read-Only device");
|
||||
READ10(sd, NULL, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Try to write a block to the Read-Only device");
|
||||
WRITE10(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Try to write a block to the Read-Only device");
|
||||
WRITE10(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_WRITE_PROTECTED);
|
||||
|
||||
finished:
|
||||
if (ms_task != NULL) {
|
||||
scsi_free_scsi_task(ms_task);
|
||||
}
|
||||
logging(LOG_VERBOSE, "Clear SWP to disable write protect");
|
||||
clear_swp(sd);
|
||||
if (ms_task != NULL) {
|
||||
scsi_free_scsi_task(ms_task);
|
||||
}
|
||||
logging(LOG_VERBOSE, "Clear SWP to disable write protect");
|
||||
clear_swp(sd);
|
||||
}
|
||||
|
||||
@@ -28,78 +28,78 @@
|
||||
void
|
||||
test_modesense6_residuals(void)
|
||||
{
|
||||
struct scsi_task *ms_task = NULL;
|
||||
struct scsi_task *ms_task = NULL;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of MODESENSE6 Residuals");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of MODESENSE6 Residuals");
|
||||
|
||||
logging(LOG_VERBOSE, "MODESENSE6 command should not result in any "
|
||||
"residuals");
|
||||
logging(LOG_VERBOSE, "MODESENSE6 command should not result in any "
|
||||
"residuals");
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try a MODESENSE6 command with 4 bytes of "
|
||||
"transfer length and verify that we don't get residuals.");
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
|
||||
logging(LOG_VERBOSE, "Try a MODESENSE6 command with 4 bytes of "
|
||||
"transfer length and verify that we don't get residuals.");
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 4,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "[SUCCESS] All Pages fetched.");
|
||||
logging(LOG_VERBOSE, "[SUCCESS] All Pages fetched.");
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that we got at most 4 bytes of DATA-IN");
|
||||
if (ms_task->datain.size > 4) {
|
||||
logging(LOG_NORMAL, "[FAILED] got more than 4 bytes of "
|
||||
"DATA-IN.");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] <= 4 bytes of DATA-IN "
|
||||
"received.");
|
||||
}
|
||||
CU_ASSERT_TRUE(ms_task->datain.size <= 4);
|
||||
logging(LOG_VERBOSE, "Verify that we got at most 4 bytes of DATA-IN");
|
||||
if (ms_task->datain.size > 4) {
|
||||
logging(LOG_NORMAL, "[FAILED] got more than 4 bytes of "
|
||||
"DATA-IN.");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] <= 4 bytes of DATA-IN "
|
||||
"received.");
|
||||
}
|
||||
CU_ASSERT_TRUE(ms_task->datain.size <= 4);
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag not set");
|
||||
if (ms_task->residual_status == SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_NOT_EQUAL(ms_task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag not set");
|
||||
if (ms_task->residual_status == SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_NOT_EQUAL(ms_task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try a MODESENSE6 command with 255 bytes of "
|
||||
"transfer length and verify that we get residuals if the target returns less than the requested amount of data.");
|
||||
scsi_free_scsi_task(ms_task);
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
logging(LOG_VERBOSE, "Try a MODESENSE6 command with 255 bytes of "
|
||||
"transfer length and verify that we get residuals if the target returns less than the requested amount of data.");
|
||||
scsi_free_scsi_task(ms_task);
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "[SUCCESS] All Pages fetched.");
|
||||
logging(LOG_VERBOSE, "[SUCCESS] All Pages fetched.");
|
||||
|
||||
if (ms_task->datain.size == 255) {
|
||||
logging(LOG_VERBOSE, "We got all 255 bytes of data back "
|
||||
"from the target. Verify that underflow is not set.");
|
||||
if (ms_task->datain.size == 255) {
|
||||
logging(LOG_VERBOSE, "We got all 255 bytes of data back "
|
||||
"from the target. Verify that underflow is not set.");
|
||||
|
||||
if (ms_task->residual_status == SCSI_RESIDUAL_UNDERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target set residual "
|
||||
"underflow flag");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Residual underflow "
|
||||
"is not set");
|
||||
}
|
||||
CU_ASSERT_NOT_EQUAL(ms_task->residual_status,
|
||||
SCSI_RESIDUAL_UNDERFLOW);
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "We got less than the requested 255 bytes "
|
||||
"from the target. Verify that underflow is set.");
|
||||
if (ms_task->residual_status == SCSI_RESIDUAL_UNDERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target set residual "
|
||||
"underflow flag");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Residual underflow "
|
||||
"is not set");
|
||||
}
|
||||
CU_ASSERT_NOT_EQUAL(ms_task->residual_status,
|
||||
SCSI_RESIDUAL_UNDERFLOW);
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "We got less than the requested 255 bytes "
|
||||
"from the target. Verify that underflow is set.");
|
||||
|
||||
if (ms_task->residual_status != SCSI_RESIDUAL_UNDERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set "
|
||||
"residual underflow flag");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Residual underflow "
|
||||
"is set");
|
||||
}
|
||||
CU_ASSERT_EQUAL(ms_task->residual_status,
|
||||
SCSI_RESIDUAL_UNDERFLOW);
|
||||
}
|
||||
if (ms_task->residual_status != SCSI_RESIDUAL_UNDERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set "
|
||||
"residual underflow flag");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Residual underflow "
|
||||
"is set");
|
||||
}
|
||||
CU_ASSERT_EQUAL(ms_task->residual_status,
|
||||
SCSI_RESIDUAL_UNDERFLOW);
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(ms_task);
|
||||
scsi_free_scsi_task(ms_task);
|
||||
}
|
||||
|
||||
@@ -32,65 +32,65 @@
|
||||
void
|
||||
test_multipathio_compareandwrite(void)
|
||||
{
|
||||
int io_bl = 1; /* 1 block CAW IOs */
|
||||
int path;
|
||||
int i, ret;
|
||||
int maxbl;
|
||||
int io_bl = 1; /* 1 block CAW IOs */
|
||||
int path;
|
||||
int i, ret;
|
||||
int maxbl;
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
MPATH_SKIP_IF_UNAVAILABLE(mp_sds, mp_num_sds);
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
MPATH_SKIP_IF_UNAVAILABLE(mp_sds, mp_num_sds);
|
||||
|
||||
if (inq_bl) {
|
||||
maxbl = inq_bl->max_cmp;
|
||||
} else {
|
||||
/* Assume we are not limited */
|
||||
maxbl = 256;
|
||||
}
|
||||
if (maxbl < io_bl) {
|
||||
CU_PASS("[SKIPPED] MAXIMUM_COMPARE_AND_WRITE_LENGTH too small");
|
||||
return;
|
||||
}
|
||||
if (inq_bl) {
|
||||
maxbl = inq_bl->max_cmp;
|
||||
} else {
|
||||
/* Assume we are not limited */
|
||||
maxbl = 256;
|
||||
}
|
||||
if (maxbl < io_bl) {
|
||||
CU_PASS("[SKIPPED] MAXIMUM_COMPARE_AND_WRITE_LENGTH too small");
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Initialising data prior to COMPARE_AND_WRITE");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Initialising data prior to COMPARE_AND_WRITE");
|
||||
|
||||
memset(scratch, 0, io_bl * block_size);
|
||||
ret = writesame10(mp_sds[0], 0,
|
||||
block_size, 256, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (ret == -2) {
|
||||
CU_PASS("[SKIPPED] Target does not support WRITESAME10. Skipping test");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
memset(scratch, 0, io_bl * block_size);
|
||||
ret = writesame10(mp_sds[0], 0,
|
||||
block_size, 256, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (ret == -2) {
|
||||
CU_PASS("[SKIPPED] Target does not support WRITESAME10. Skipping test");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Test multipath COMPARE_AND_WRITE");
|
||||
for (i = 0; i < 256; i++) {
|
||||
logging(LOG_VERBOSE, "Test multipath COMPARE_AND_WRITE");
|
||||
for (i = 0; i < 256; i++) {
|
||||
|
||||
for (path = 0; path < mp_num_sds; path++) {
|
||||
logging(LOG_VERBOSE,
|
||||
"Test COMPARE_AND_WRITE(%d->%d) using path %d",
|
||||
path, path + 1, path);
|
||||
for (path = 0; path < mp_num_sds; path++) {
|
||||
logging(LOG_VERBOSE,
|
||||
"Test COMPARE_AND_WRITE(%d->%d) using path %d",
|
||||
path, path + 1, path);
|
||||
|
||||
/* compare data is first half */
|
||||
memset(scratch, path, io_bl * block_size);
|
||||
/* write data is the second half, wrap around */
|
||||
memset(scratch + io_bl * block_size, path + 1,
|
||||
io_bl * block_size);
|
||||
COMPAREANDWRITE(mp_sds[path], i,
|
||||
/* compare data is first half */
|
||||
memset(scratch, path, io_bl * block_size);
|
||||
/* write data is the second half, wrap around */
|
||||
memset(scratch + io_bl * block_size, path + 1,
|
||||
io_bl * block_size);
|
||||
COMPAREANDWRITE(mp_sds[path], i,
|
||||
scratch, 2 * io_bl * block_size,
|
||||
block_size, 0, 0, 0, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE,
|
||||
"Test bad COMPARE_AND_WRITE(%d->%d)",
|
||||
path, path + 1);
|
||||
logging(LOG_VERBOSE,
|
||||
"Test bad COMPARE_AND_WRITE(%d->%d)",
|
||||
path, path + 1);
|
||||
|
||||
COMPAREANDWRITE(mp_sds[path], i,
|
||||
COMPAREANDWRITE(mp_sds[path], i,
|
||||
scratch, 2 * io_bl * block_size,
|
||||
block_size, 0, 0, 0, 0,
|
||||
EXPECT_MISCOMPARE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,43 +31,43 @@
|
||||
void
|
||||
test_multipathio_reset(void)
|
||||
{
|
||||
int reset_path;
|
||||
int reset_path;
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
MPATH_SKIP_IF_UNAVAILABLE(mp_sds, mp_num_sds);
|
||||
MPATH_SKIP_UNLESS_ISCSI(mp_sds, mp_num_sds);
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
MPATH_SKIP_IF_UNAVAILABLE(mp_sds, mp_num_sds);
|
||||
MPATH_SKIP_UNLESS_ISCSI(mp_sds, mp_num_sds);
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
|
||||
for (reset_path = 0; reset_path < mp_num_sds; reset_path++) {
|
||||
int num_uas;
|
||||
int ret;
|
||||
int tur_path;
|
||||
struct scsi_device *reset_sd = mp_sds[reset_path];
|
||||
for (reset_path = 0; reset_path < mp_num_sds; reset_path++) {
|
||||
int num_uas;
|
||||
int ret;
|
||||
int tur_path;
|
||||
struct scsi_device *reset_sd = mp_sds[reset_path];
|
||||
|
||||
logging(LOG_VERBOSE, "Awaiting good TUR");
|
||||
ret = test_iscsi_tur_until_good(reset_sd, &num_uas);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "Awaiting good TUR");
|
||||
ret = test_iscsi_tur_until_good(reset_sd, &num_uas);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE,
|
||||
"Test multipath LUN Reset using path %d", reset_path);
|
||||
logging(LOG_VERBOSE,
|
||||
"Test multipath LUN Reset using path %d", reset_path);
|
||||
|
||||
ret = iscsi_task_mgmt_lun_reset_sync(reset_sd->iscsi_ctx,
|
||||
reset_sd->iscsi_lun);
|
||||
if (ret != 0) {
|
||||
logging(LOG_NORMAL, "LUN reset failed. %s",
|
||||
iscsi_get_error(reset_sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
ret = iscsi_task_mgmt_lun_reset_sync(reset_sd->iscsi_ctx,
|
||||
reset_sd->iscsi_lun);
|
||||
if (ret != 0) {
|
||||
logging(LOG_NORMAL, "LUN reset failed. %s",
|
||||
iscsi_get_error(reset_sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
/* check for and clear LU reset UA on all paths */
|
||||
for (tur_path = 0; tur_path < mp_num_sds; tur_path++) {
|
||||
logging(LOG_VERBOSE, "check for LU reset unit "
|
||||
"attention via TUR on path %d", tur_path);
|
||||
ret = test_iscsi_tur_until_good(mp_sds[tur_path], &num_uas);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
CU_ASSERT_NOT_EQUAL(num_uas, 0);
|
||||
}
|
||||
}
|
||||
/* check for and clear LU reset UA on all paths */
|
||||
for (tur_path = 0; tur_path < mp_num_sds; tur_path++) {
|
||||
logging(LOG_VERBOSE, "check for LU reset unit "
|
||||
"attention via TUR on path %d", tur_path);
|
||||
ret = test_iscsi_tur_until_good(mp_sds[tur_path], &num_uas);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
CU_ASSERT_NOT_EQUAL(num_uas, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,44 +31,44 @@
|
||||
void
|
||||
test_multipathio_simple(void)
|
||||
{
|
||||
int write_path;
|
||||
unsigned char *write_buf = alloca(256 * block_size);
|
||||
unsigned char *read_buf = alloca(256 * block_size);
|
||||
int write_path;
|
||||
unsigned char *write_buf = alloca(256 * block_size);
|
||||
unsigned char *read_buf = alloca(256 * block_size);
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
MPATH_SKIP_IF_UNAVAILABLE(mp_sds, mp_num_sds);
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
MPATH_SKIP_IF_UNAVAILABLE(mp_sds, mp_num_sds);
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
memset(write_buf, 0xa6, 256 * block_size);
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
memset(write_buf, 0xa6, 256 * block_size);
|
||||
|
||||
for (write_path = 0; write_path < mp_num_sds; write_path++) {
|
||||
int i;
|
||||
int read_path;
|
||||
for (write_path = 0; write_path < mp_num_sds; write_path++) {
|
||||
int i;
|
||||
int read_path;
|
||||
|
||||
/* read back written data using a different path */
|
||||
read_path = (write_path + 1) % mp_num_sds;
|
||||
/* read back written data using a different path */
|
||||
read_path = (write_path + 1) % mp_num_sds;
|
||||
|
||||
logging(LOG_VERBOSE,
|
||||
"Test multipath WRITE10/READ10 of 1-256 blocks using "
|
||||
"path %d", write_path);
|
||||
logging(LOG_VERBOSE,
|
||||
"Test multipath WRITE10/READ10 of 1-256 blocks using "
|
||||
"path %d", write_path);
|
||||
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length
|
||||
&& maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
WRITE10(mp_sds[write_path], 0, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, write_buf,
|
||||
EXPECT_STATUS_GOOD);
|
||||
READ10(mp_sds[read_path], NULL, 0, i * block_size,
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length
|
||||
&& maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
WRITE10(mp_sds[write_path], 0, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, write_buf,
|
||||
EXPECT_STATUS_GOOD);
|
||||
READ10(mp_sds[read_path], NULL, 0, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, read_buf,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
/* compare written and read data */
|
||||
CU_ASSERT_EQUAL(0,
|
||||
memcmp(write_buf, read_buf, i * block_size));
|
||||
}
|
||||
/* compare written and read data */
|
||||
CU_ASSERT_EQUAL(0,
|
||||
memcmp(write_buf, read_buf, i * block_size));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,64 +28,64 @@
|
||||
static void
|
||||
test_synchronizecache10(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test SYNCHRONIZECACHE10 when medium is ejected.");
|
||||
SYNCHRONIZECACHE10(sd, 0, 1, 1, 1,
|
||||
logging(LOG_VERBOSE, "Test SYNCHRONIZECACHE10 when medium is ejected.");
|
||||
SYNCHRONIZECACHE10(sd, 0, 1, 1, 1,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
test_synchronizecache16(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test SYNCHRONIZECACHE16 when medium is ejected.");
|
||||
SYNCHRONIZECACHE16(sd, 0, 1, 1, 1,
|
||||
logging(LOG_VERBOSE, "Test SYNCHRONIZECACHE16 when medium is ejected.");
|
||||
SYNCHRONIZECACHE16(sd, 0, 1, 1, 1,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read10(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test READ10 when medium is ejected.");
|
||||
READ10(sd, NULL, 0, block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, "Test READ10 when medium is ejected.");
|
||||
READ10(sd, NULL, 0, block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read12(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test READ12 when medium is ejected.");
|
||||
READ12(sd, NULL, 0, block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, "Test READ12 when medium is ejected.");
|
||||
READ12(sd, NULL, 0, block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read16(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test READ16 when medium is ejected.");
|
||||
READ16(sd, NULL, 0, block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, "Test READ16 when medium is ejected.");
|
||||
READ16(sd, NULL, 0, block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
test_write10(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test WRITE10 when medium is ejected.");
|
||||
WRITE10(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Test WRITE10 when medium is ejected.");
|
||||
WRITE10(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
test_write12(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test WRITE12 when medium is ejected.");
|
||||
WRITE12(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Test WRITE12 when medium is ejected.");
|
||||
WRITE12(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
test_write16(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test WRITE16 when medium is ejected.");
|
||||
WRITE16(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Test WRITE16 when medium is ejected.");
|
||||
WRITE16(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ static void
|
||||
test_writeverify10(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test WRITEVERIFY10 when medium is ejected.");
|
||||
WRITEVERIFY10(sd, 0, block_size, block_size, 0, 0, 0, 0, scratch,
|
||||
WRITEVERIFY10(sd, 0, block_size, block_size, 0, 0, 0, 0, scratch,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ static void
|
||||
test_writeverify12(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test WRITEVERIFY12 when medium is ejected.");
|
||||
WRITEVERIFY12(sd, 0, block_size, block_size, 0, 0, 0, 0, scratch,
|
||||
WRITEVERIFY12(sd, 0, block_size, block_size, 0, 0, 0, 0, scratch,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
@@ -109,68 +109,68 @@ static void
|
||||
test_writeverify16(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test WRITEVERIFY16 when medium is ejected.");
|
||||
WRITEVERIFY16(sd, 0, block_size, block_size, 0, 0, 0, 0, scratch,
|
||||
WRITEVERIFY16(sd, 0, block_size, block_size, 0, 0, 0, 0, scratch,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
test_verify10(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test VERIFY10 when medium is ejected.");
|
||||
VERIFY10(sd, 0, block_size, block_size, 0, 0, 1, scratch,
|
||||
logging(LOG_VERBOSE, "Test VERIFY10 when medium is ejected.");
|
||||
VERIFY10(sd, 0, block_size, block_size, 0, 0, 1, scratch,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
static void
|
||||
test_verify12(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test VERIFY12 when medium is ejected.");
|
||||
VERIFY12(sd, 0, block_size, block_size, 0, 0, 1, scratch,
|
||||
logging(LOG_VERBOSE, "Test VERIFY12 when medium is ejected.");
|
||||
VERIFY12(sd, 0, block_size, block_size, 0, 0, 1, scratch,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
static void
|
||||
test_verify16(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test VERIFY16 when medium is ejected.");
|
||||
VERIFY16(sd, 0, block_size, block_size, 0, 0, 1, scratch,
|
||||
logging(LOG_VERBOSE, "Test VERIFY16 when medium is ejected.");
|
||||
VERIFY16(sd, 0, block_size, block_size, 0, 0, 1, scratch,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
test_getlbastatus(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test GET_LBA_STATUS when medium is ejected.");
|
||||
GETLBASTATUS(sd, NULL, 0, 24,
|
||||
logging(LOG_VERBOSE, "Test GET_LBA_STATUS when medium is ejected.");
|
||||
GETLBASTATUS(sd, NULL, 0, 24,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
test_prefetch10(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 when medium is ejected.");
|
||||
PREFETCH10(sd, 0, 1, 1, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 when medium is ejected.");
|
||||
PREFETCH10(sd, 0, 1, 1, 0,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
test_prefetch16(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 when medium is ejected.");
|
||||
PREFETCH16(sd, 0, 1, 1, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 when medium is ejected.");
|
||||
PREFETCH16(sd, 0, 1, 1, 0,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
test_orwrite(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test ORWRITE when medium is ejected.");
|
||||
ORWRITE(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Test ORWRITE when medium is ejected.");
|
||||
ORWRITE(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
test_compareandwrite(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test COMPAREANDWRITE when medium is ejected.");
|
||||
logging(LOG_VERBOSE, "Test COMPAREANDWRITE when medium is ejected.");
|
||||
COMPAREANDWRITE(sd, 0, scratch, 2 * block_size, block_size, 0, 0, 0, 0,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
@@ -178,36 +178,36 @@ test_compareandwrite(void)
|
||||
static void
|
||||
test_writesame10(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test WRITESAME10 when medium is ejected.");
|
||||
WRITESAME10(sd, 0, block_size, 1, 0, 0, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Test WRITESAME10 when medium is ejected.");
|
||||
WRITESAME10(sd, 0, block_size, 1, 0, 0, 0, 0, scratch,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
test_writesame16(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test WRITESAME16 when medium is ejected.");
|
||||
WRITESAME16(sd, 0, block_size, 1, 0, 0, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Test WRITESAME16 when medium is ejected.");
|
||||
WRITESAME16(sd, 0, block_size, 1, 0, 0, 0, 0, scratch,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
test_unmap(void)
|
||||
{
|
||||
struct unmap_list list[1];
|
||||
struct unmap_list list[1];
|
||||
|
||||
logging(LOG_VERBOSE, "Test UNMAP when medium is ejected.");
|
||||
list[0].lba = 0;
|
||||
list[0].num = lbppb;
|
||||
UNMAP(sd, 0, list, 1,
|
||||
EXPECT_NO_MEDIUM);
|
||||
list[0].lba = 0;
|
||||
list[0].num = lbppb;
|
||||
UNMAP(sd, 0, list, 1,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
static void
|
||||
test_readcapacity10(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test READCAPACITY10 when medium is ejected.");
|
||||
READCAPACITY10(sd, NULL, 0, 0,
|
||||
READCAPACITY10(sd, NULL, 0, 0,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
@@ -215,30 +215,30 @@ static void
|
||||
test_readcapacity16(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test READCAPACITY16 when medium is ejected.");
|
||||
READCAPACITY16(sd, NULL, 15,
|
||||
READCAPACITY16(sd, NULL, 15,
|
||||
EXPECT_NO_MEDIUM);
|
||||
}
|
||||
|
||||
void
|
||||
test_nomedia_sbc(void)
|
||||
{
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that Medium commands fail when medium is ejected on SBC devices");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that Medium commands fail when medium is ejected on SBC devices");
|
||||
|
||||
if (!inq->rmb) {
|
||||
logging(LOG_VERBOSE, "[SKIPPED] LUN is not removable. "
|
||||
"Skipping test.");
|
||||
return;
|
||||
}
|
||||
if (!inq->rmb) {
|
||||
logging(LOG_VERBOSE, "[SKIPPED] LUN is not removable. "
|
||||
"Skipping test.");
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Eject the medium.");
|
||||
STARTSTOPUNIT(sd, 1, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Eject the medium.");
|
||||
STARTSTOPUNIT(sd, 1, 0, 0, 0, 1, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Test TESTUNITREADY when medium is ejected.");
|
||||
TESTUNITREADY(sd,
|
||||
logging(LOG_VERBOSE, "Test TESTUNITREADY when medium is ejected.");
|
||||
TESTUNITREADY(sd,
|
||||
EXPECT_NO_MEDIUM);
|
||||
|
||||
test_synchronizecache10();
|
||||
@@ -255,10 +255,10 @@ test_nomedia_sbc(void)
|
||||
test_prefetch10();
|
||||
test_prefetch16();
|
||||
|
||||
if (!data_loss) {
|
||||
logging(LOG_VERBOSE, "[SKIPPING] Dataloss flag not set. Skipping test for WRITE commands");
|
||||
goto finished;
|
||||
}
|
||||
if (!data_loss) {
|
||||
logging(LOG_VERBOSE, "[SKIPPING] Dataloss flag not set. Skipping test for WRITE commands");
|
||||
goto finished;
|
||||
}
|
||||
|
||||
test_compareandwrite();
|
||||
test_orwrite();
|
||||
@@ -273,7 +273,7 @@ test_nomedia_sbc(void)
|
||||
test_writeverify16();
|
||||
|
||||
finished:
|
||||
logging(LOG_VERBOSE, "Load the medium again.");
|
||||
STARTSTOPUNIT(sd, 1, 0, 0, 0, 1, 1,
|
||||
logging(LOG_VERBOSE, "Load the medium again.");
|
||||
STARTSTOPUNIT(sd, 1, 0, 0, 0, 1, 1,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
|
||||
@@ -27,23 +27,23 @@
|
||||
void
|
||||
test_orwrite_0blocks(void)
|
||||
{
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test ORWRITE 0-blocks at LBA==0");
|
||||
ORWRITE(sd, 0, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test ORWRITE 0-blocks at LBA==0");
|
||||
ORWRITE(sd, 0, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Test ORWRITE 0-blocks one block past end-of-LUN");
|
||||
ORWRITE(sd, num_blocks + 1, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, "Test ORWRITE 0-blocks one block past end-of-LUN");
|
||||
ORWRITE(sd, num_blocks + 1, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
|
||||
logging(LOG_VERBOSE, "Test ORWRITE 0-blocks at LBA==2^63");
|
||||
ORWRITE(sd, 0x8000000000000000ULL, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, "Test ORWRITE 0-blocks at LBA==2^63");
|
||||
ORWRITE(sd, 0x8000000000000000ULL, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
|
||||
logging(LOG_VERBOSE, "Test ORWRITE 0-blocks at LBA==-1");
|
||||
ORWRITE(sd, -1, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, "Test ORWRITE 0-blocks at LBA==-1");
|
||||
ORWRITE(sd, -1, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
|
||||
@@ -29,53 +29,53 @@
|
||||
void
|
||||
test_orwrite_beyond_eol(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test ORWRITE 1-256 blocks one block beyond the end");
|
||||
memset(scratch, 0xa6, 256 * block_size);
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
ORWRITE(sd, num_blocks + 1 - i,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test ORWRITE 1-256 blocks one block beyond the end");
|
||||
memset(scratch, 0xa6, 256 * block_size);
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
ORWRITE(sd, num_blocks + 1 - i,
|
||||
i * block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Test ORWRITE 1-256 blocks at LBA==2^63");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
ORWRITE(sd, 0x8000000000000000ULL, i * block_size, block_size,
|
||||
logging(LOG_VERBOSE, "Test ORWRITE 1-256 blocks at LBA==2^63");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
ORWRITE(sd, 0x8000000000000000ULL, i * block_size, block_size,
|
||||
0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Test ORWRITE 1-256 blocks at LBA==-1");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
ORWRITE(sd, -1, i * block_size, block_size,
|
||||
logging(LOG_VERBOSE, "Test ORWRITE 1-256 blocks at LBA==-1");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
ORWRITE(sd, -1, i * block_size, block_size,
|
||||
0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Test ORWRITE 2-256 blocks all but one block beyond the end");
|
||||
for (i = 2; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
ORWRITE(sd, num_blocks - 1, i * block_size, block_size,
|
||||
logging(LOG_VERBOSE, "Test ORWRITE 2-256 blocks all but one block beyond the end");
|
||||
for (i = 2; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
ORWRITE(sd, num_blocks - 1, i * block_size, block_size,
|
||||
0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,75 +29,75 @@
|
||||
void
|
||||
test_orwrite_dpofua(void)
|
||||
{
|
||||
int dpofua, usage_data_dpofua;
|
||||
struct scsi_task *ms_task = NULL;
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_task *rso_task = NULL;
|
||||
struct scsi_report_supported_op_codes_one_command *rsoc;
|
||||
int dpofua, usage_data_dpofua;
|
||||
struct scsi_task *ms_task = NULL;
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_task *rso_task = NULL;
|
||||
struct scsi_report_supported_op_codes_one_command *rsoc;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test ORWRITE DPO/FUA flags");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test ORWRITE DPO/FUA flags");
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_DATALOSS;
|
||||
|
||||
logging(LOG_VERBOSE, "Read the DPOFUA flag from mode sense data");
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
logging(LOG_VERBOSE, "Read the DPOFUA flag from mode sense data");
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode sense returned status GOOD");
|
||||
ms = scsi_datain_unmarshall(ms_task);
|
||||
dpofua = ms && (ms->device_specific_parameter & 0x10);
|
||||
scsi_free_scsi_task(ms_task);
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode sense returned status GOOD");
|
||||
ms = scsi_datain_unmarshall(ms_task);
|
||||
dpofua = ms && (ms->device_specific_parameter & 0x10);
|
||||
scsi_free_scsi_task(ms_task);
|
||||
|
||||
if (dpofua) {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is set. Device should allow "
|
||||
"DPO/FUA flags in CDBs");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is clear. Device should fail "
|
||||
"CDBs with DPO/FUA set");
|
||||
}
|
||||
if (dpofua) {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is set. Device should allow "
|
||||
"DPO/FUA flags in CDBs");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is clear. Device should fail "
|
||||
"CDBs with DPO/FUA set");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test ORWRITE with DPO==1");
|
||||
memset(scratch, 0xa6, block_size);
|
||||
if (dpofua) {
|
||||
ORWRITE(sd, 0, block_size, block_size, 0, 1, 0, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Test ORWRITE with DPO==1");
|
||||
memset(scratch, 0xa6, block_size);
|
||||
if (dpofua) {
|
||||
ORWRITE(sd, 0, block_size, block_size, 0, 1, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
} else {
|
||||
ORWRITE(sd, 0, block_size, block_size, 0, 1, 0, 0, 0, scratch,
|
||||
} else {
|
||||
ORWRITE(sd, 0, block_size, block_size, 0, 1, 0, 0, 0, scratch,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test ORWRITE with FUA==1");
|
||||
if (dpofua) {
|
||||
ORWRITE(sd, 0, block_size, block_size, 0, 0, 1, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Test ORWRITE with FUA==1");
|
||||
if (dpofua) {
|
||||
ORWRITE(sd, 0, block_size, block_size, 0, 0, 1, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
} else {
|
||||
ORWRITE(sd, 0, block_size, block_size, 0, 0, 1, 0, 0, scratch,
|
||||
} else {
|
||||
ORWRITE(sd, 0, block_size, block_size, 0, 0, 1, 0, 0, scratch,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test ORWRITE with DPO==1 FUA==1");
|
||||
if (dpofua) {
|
||||
ORWRITE(sd, 0, block_size, block_size, 0, 1, 1, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Test ORWRITE with DPO==1 FUA==1");
|
||||
if (dpofua) {
|
||||
ORWRITE(sd, 0, block_size, block_size, 0, 1, 1, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
} else {
|
||||
ORWRITE(sd, 0, block_size, block_size, 0, 1, 1, 0, 0, scratch,
|
||||
} else {
|
||||
ORWRITE(sd, 0, block_size, block_size, 0, 1, 1, 0, 0, scratch,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Try fetching REPORT_SUPPORTED_OPCODES "
|
||||
"for ORWRITE");
|
||||
REPORT_SUPPORTED_OPCODES(sd, &rso_task,
|
||||
logging(LOG_VERBOSE, "Try fetching REPORT_SUPPORTED_OPCODES "
|
||||
"for ORWRITE");
|
||||
REPORT_SUPPORTED_OPCODES(sd, &rso_task,
|
||||
0, SCSI_REPORT_SUPPORTING_OPCODE,
|
||||
SCSI_OPCODE_ORWRITE,
|
||||
0,
|
||||
65535,
|
||||
EXPECT_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc);
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc);
|
||||
|
||||
usage_data_dpofua = rsoc->cdb_usage_data[1] & 0x18;
|
||||
if (dpofua) {
|
||||
@@ -118,5 +118,5 @@ test_orwrite_dpofua(void)
|
||||
}
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(rso_task);
|
||||
scsi_free_scsi_task(rso_task);
|
||||
}
|
||||
|
||||
@@ -30,30 +30,30 @@
|
||||
void
|
||||
test_orwrite_simple(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test ORWRITE of 1-256 blocks at the start of the LUN");
|
||||
memset(scratch, 0xa6, 256 * block_size);
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
ORWRITE(sd, 0, i * block_size,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test ORWRITE of 1-256 blocks at the start of the LUN");
|
||||
memset(scratch, 0xa6, 256 * block_size);
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
ORWRITE(sd, 0, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test ORWRITE of 1-256 blocks at the end of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
ORWRITE(sd, num_blocks - i, i * block_size, block_size,
|
||||
logging(LOG_VERBOSE, "Test ORWRITE of 1-256 blocks at the end of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
ORWRITE(sd, num_blocks - i, i * block_size, block_size,
|
||||
0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,101 +31,101 @@
|
||||
void
|
||||
test_orwrite_verify(void)
|
||||
{
|
||||
int i, ret;
|
||||
unsigned char *buf = &scratch[0];
|
||||
unsigned char *readbuf = &scratch[256 * block_size];
|
||||
int i, ret;
|
||||
unsigned char *buf = &scratch[0];
|
||||
unsigned char *readbuf = &scratch[256 * block_size];
|
||||
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test ORWRITE of 1-256 blocks at the start of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test ORWRITE of 1-256 blocks at the start of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Write %d blocks of all-zero", i);
|
||||
memset(buf, 0, block_size * i);
|
||||
ret = write10(sd, 0, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, buf,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "Write %d blocks of all-zero", i);
|
||||
memset(buf, 0, block_size * i);
|
||||
ret = write10(sd, 0, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, buf,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "OrWrite %d blocks with 0xa5", i);
|
||||
memset(buf, 0xa5, block_size * i);
|
||||
ORWRITE(sd, 0, i * block_size,
|
||||
logging(LOG_VERBOSE, "OrWrite %d blocks with 0xa5", i);
|
||||
memset(buf, 0xa5, block_size * i);
|
||||
ORWRITE(sd, 0, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, buf,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Read %d blocks back", i);
|
||||
READ10(sd, NULL, 0, i * block_size,
|
||||
logging(LOG_VERBOSE, "Read %d blocks back", i);
|
||||
READ10(sd, NULL, 0, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, readbuf,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the blocks are all 0xa5");
|
||||
ret = memcmp(buf, readbuf, block_size * i);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "Verify that the blocks are all 0xa5");
|
||||
ret = memcmp(buf, readbuf, block_size * i);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "OrWrite %d blocks with 0x5a", i);
|
||||
memset(buf, 0x5a, block_size * i);
|
||||
ORWRITE(sd, 0, i * block_size,
|
||||
logging(LOG_VERBOSE, "OrWrite %d blocks with 0x5a", i);
|
||||
memset(buf, 0x5a, block_size * i);
|
||||
ORWRITE(sd, 0, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, buf,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Read %d blocks back", i);
|
||||
READ10(sd, NULL, 0, i * block_size,
|
||||
logging(LOG_VERBOSE, "Read %d blocks back", i);
|
||||
READ10(sd, NULL, 0, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, readbuf,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the blocks are all 0xff");
|
||||
memset(buf, 0xff, block_size * i);
|
||||
ret = memcmp(buf, readbuf, block_size * i);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify that the blocks are all 0xff");
|
||||
memset(buf, 0xff, block_size * i);
|
||||
ret = memcmp(buf, readbuf, block_size * i);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test ORWRITE of 1-256 blocks at the end of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Test ORWRITE of 1-256 blocks at the end of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Write %d blocks of all-zero", i);
|
||||
memset(buf, 0, block_size * i);
|
||||
WRITE16(sd, num_blocks - i, i * block_size,
|
||||
logging(LOG_VERBOSE, "Write %d blocks of all-zero", i);
|
||||
memset(buf, 0, block_size * i);
|
||||
WRITE16(sd, num_blocks - i, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, buf,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "OrWrite %d blocks with 0xa5", i);
|
||||
memset(buf, 0xa5, block_size * i);
|
||||
ORWRITE(sd, num_blocks - i, i * block_size,
|
||||
logging(LOG_VERBOSE, "OrWrite %d blocks with 0xa5", i);
|
||||
memset(buf, 0xa5, block_size * i);
|
||||
ORWRITE(sd, num_blocks - i, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, buf,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Read %d blocks back", i);
|
||||
READ16(sd, NULL, num_blocks - i, i * block_size,
|
||||
logging(LOG_VERBOSE, "Read %d blocks back", i);
|
||||
READ16(sd, NULL, num_blocks - i, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, readbuf,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the blocks are all 0xa5");
|
||||
ret = memcmp(buf, readbuf, block_size * i);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "Verify that the blocks are all 0xa5");
|
||||
ret = memcmp(buf, readbuf, block_size * i);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "OrWrite %d blocks with 0x5a", i);
|
||||
memset(buf, 0x5a, block_size * i);
|
||||
ORWRITE(sd, num_blocks - i, i * block_size,
|
||||
logging(LOG_VERBOSE, "OrWrite %d blocks with 0x5a", i);
|
||||
memset(buf, 0x5a, block_size * i);
|
||||
ORWRITE(sd, num_blocks - i, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, buf,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Read %d blocks back", i);
|
||||
READ16(sd, NULL, num_blocks - i, i * block_size,
|
||||
logging(LOG_VERBOSE, "Read %d blocks back", i);
|
||||
READ16(sd, NULL, num_blocks - i, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, readbuf,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the blocks are all 0xff");
|
||||
memset(buf, 0xff, block_size * i);
|
||||
ret = memcmp(buf, readbuf, block_size * i);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify that the blocks are all 0xff");
|
||||
memset(buf, 0xff, block_size * i);
|
||||
ret = memcmp(buf, readbuf, block_size * i);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,27 +30,27 @@
|
||||
void
|
||||
test_orwrite_wrprotect(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Try out different non-zero values for WRPROTECT.
|
||||
*/
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test ORWRITE with non-zero WRPROTECT");
|
||||
/*
|
||||
* Try out different non-zero values for WRPROTECT.
|
||||
*/
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test ORWRITE with non-zero WRPROTECT");
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
memset(scratch, 0xa6, block_size);
|
||||
if (!inq->protect || (rc16 != NULL && !rc16->prot_en)) {
|
||||
logging(LOG_VERBOSE, "Device does not support/use protection information. All commands should fail.");
|
||||
for (i = 1; i < 8; i++) {
|
||||
ORWRITE(sd, 0, block_size,
|
||||
memset(scratch, 0xa6, block_size);
|
||||
if (!inq->protect || (rc16 != NULL && !rc16->prot_en)) {
|
||||
logging(LOG_VERBOSE, "Device does not support/use protection information. All commands should fail.");
|
||||
for (i = 1; i < 8; i++) {
|
||||
ORWRITE(sd, 0, block_size,
|
||||
block_size, i, 0, 0, 0, 0, scratch,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_NORMAL, "No tests for devices that support protection information yet.");
|
||||
logging(LOG_NORMAL, "No tests for devices that support protection information yet.");
|
||||
}
|
||||
|
||||
@@ -27,26 +27,26 @@
|
||||
void
|
||||
test_prefetch10_0blocks(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 0-blocks at LBA==0");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 0-blocks at LBA==0");
|
||||
|
||||
PREFETCH10(sd, 0, 0, 0, 0,
|
||||
PREFETCH10(sd, 0, 0, 0, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
if (num_blocks > 0x80000000) {
|
||||
CU_PASS("[SKIPPED] LUN is too big");
|
||||
return;
|
||||
}
|
||||
if (num_blocks > 0x80000000) {
|
||||
CU_PASS("[SKIPPED] LUN is too big");
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 0-blocks one block past end-of-LUN");
|
||||
PREFETCH10(sd, num_blocks + 1, 0, 0, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 0-blocks one block past end-of-LUN");
|
||||
PREFETCH10(sd, num_blocks + 1, 0, 0, 0,
|
||||
EXPECT_LBA_OOB);
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 0-blocks at LBA==2^31");
|
||||
PREFETCH10(sd, 0x80000000, 0, 0, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 0-blocks at LBA==2^31");
|
||||
PREFETCH10(sd, 0x80000000, 0, 0, 0,
|
||||
EXPECT_LBA_OOB);
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 0-blocks at LBA==-1");
|
||||
PREFETCH10(sd, -1, 0, 0, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 0-blocks at LBA==-1");
|
||||
PREFETCH10(sd, -1, 0, 0, 0,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
|
||||
@@ -28,35 +28,35 @@
|
||||
void
|
||||
test_prefetch10_beyond_eol(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if (num_blocks >= 0x80000000) {
|
||||
CU_PASS("LUN is too big for read-beyond-eol tests with PREFETCH10. Skipping test.\n");
|
||||
return;
|
||||
}
|
||||
if (num_blocks >= 0x80000000) {
|
||||
CU_PASS("LUN is too big for read-beyond-eol tests with PREFETCH10. Skipping test.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 1-256 blocks one block beyond the end");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH10(sd, num_blocks + 1 - i, i, 0, 0,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 1-256 blocks one block beyond the end");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH10(sd, num_blocks + 1 - i, i, 0, 0,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 1-256 blocks at LBA==2^31");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH10(sd, 0x80000000, i, 0, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 1-256 blocks at LBA==2^31");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH10(sd, 0x80000000, i, 0, 0,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 1-256 blocks at LBA==-1");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH10(sd, -1, i, 0, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 1-256 blocks at LBA==-1");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH10(sd, -1, i, 0, 0,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 2-256 blocks all but one block beyond the end");
|
||||
for (i = 2; i <= 256; i++) {
|
||||
PREFETCH10(sd, num_blocks - 1, i, 0, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 2-256 blocks all but one block beyond the end");
|
||||
for (i = 2; i <= 256; i++) {
|
||||
PREFETCH10(sd, num_blocks - 1, i, 0, 0,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,18 +29,18 @@
|
||||
void
|
||||
test_prefetch10_flags(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 flags");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 flags");
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 with IMMED==1");
|
||||
PREFETCH10(sd, 0, 1, 1, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 with IMMED==1");
|
||||
PREFETCH10(sd, 0, 1, 1, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 with GROUP==3");
|
||||
PREFETCH10(sd, 0, 1, 0, 3,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 with GROUP==3");
|
||||
PREFETCH10(sd, 0, 1, 0, 3,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 with IMMED=1 and GROUP==3");
|
||||
PREFETCH10(sd, 0, 1, 1, 3,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 with IMMED=1 and GROUP==3");
|
||||
PREFETCH10(sd, 0, 1, 1, 3,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
|
||||
@@ -29,19 +29,19 @@
|
||||
void
|
||||
test_prefetch10_simple(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 of 1-256 blocks at the start of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH10(sd, 0, i, 0, 0,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 of 1-256 blocks at the start of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH10(sd, 0, i, 0, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 of 1-256 blocks at the end of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH10(sd, num_blocks - i, i, 0, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH10 of 1-256 blocks at the end of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH10(sd, num_blocks - i, i, 0, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,21 +27,21 @@
|
||||
void
|
||||
test_prefetch16_0blocks(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 0-blocks at LBA==0");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 0-blocks at LBA==0");
|
||||
|
||||
PREFETCH16(sd, 0, 0, 0, 0,
|
||||
PREFETCH16(sd, 0, 0, 0, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 0-blocks one block past end-of-LUN");
|
||||
PREFETCH16(sd, num_blocks + 1, 0, 0, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 0-blocks one block past end-of-LUN");
|
||||
PREFETCH16(sd, num_blocks + 1, 0, 0, 0,
|
||||
EXPECT_LBA_OOB);
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 0-blocks at LBA==2^63");
|
||||
PREFETCH16(sd, 0x8000000000000000ULL, 0, 0, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 0-blocks at LBA==2^63");
|
||||
PREFETCH16(sd, 0x8000000000000000ULL, 0, 0, 0,
|
||||
EXPECT_LBA_OOB);
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 0-blocks at LBA==-1");
|
||||
PREFETCH16(sd, -1, 0, 0, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 0-blocks at LBA==-1");
|
||||
PREFETCH16(sd, -1, 0, 0, 0,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
|
||||
@@ -28,30 +28,30 @@
|
||||
void
|
||||
test_prefetch16_beyond_eol(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 1-256 blocks one block beyond the end");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH16(sd, num_blocks + 1 - i, i, 0, 0,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 1-256 blocks one block beyond the end");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH16(sd, num_blocks + 1 - i, i, 0, 0,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 1-256 blocks at LBA==2^63");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH16(sd, 0x8000000000000000ULL, i, 0, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 1-256 blocks at LBA==2^63");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH16(sd, 0x8000000000000000ULL, i, 0, 0,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 1-256 blocks at LBA==-1");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH16(sd, -1, i, 0, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 1-256 blocks at LBA==-1");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH16(sd, -1, i, 0, 0,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 2-256 blocks all but one block beyond the end");
|
||||
for (i = 2; i <= 256; i++) {
|
||||
PREFETCH16(sd, num_blocks - 1, i, 0, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 2-256 blocks all but one block beyond the end");
|
||||
for (i = 2; i <= 256; i++) {
|
||||
PREFETCH16(sd, num_blocks - 1, i, 0, 0,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,18 +29,18 @@
|
||||
void
|
||||
test_prefetch16_flags(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 flags");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 flags");
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 with IMMED==1");
|
||||
PREFETCH16(sd, 0, 1, 1, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 with IMMED==1");
|
||||
PREFETCH16(sd, 0, 1, 1, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 with GROUP==3");
|
||||
PREFETCH16(sd, 0, 1, 0, 3,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 with GROUP==3");
|
||||
PREFETCH16(sd, 0, 1, 0, 3,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 with IMMED=1 and GROUP==3");
|
||||
PREFETCH16(sd, 0, 1, 1, 3,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 with IMMED=1 and GROUP==3");
|
||||
PREFETCH16(sd, 0, 1, 1, 3,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
|
||||
@@ -29,19 +29,19 @@
|
||||
void
|
||||
test_prefetch16_simple(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 of 1-256 blocks at the start of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH16(sd, 0, i, 0, 0,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 of 1-256 blocks at the start of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH16(sd, 0, i, 0, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 of 1-256 blocks at the end of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH16(sd, num_blocks - i, i, 0, 0,
|
||||
logging(LOG_VERBOSE, "Test PREFETCH16 of 1-256 blocks at the end of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
PREFETCH16(sd, num_blocks - i, i, 0, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,52 +29,52 @@
|
||||
void
|
||||
test_preventallow_2_itnexuses(void)
|
||||
{
|
||||
int ret;
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
struct scsi_device *sd2;
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_REMOVABLE;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_REMOVABLE;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that PREVENT MEDIUM REMOVAL are seen on other nexuses as well");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that PREVENT MEDIUM REMOVAL are seen on other nexuses as well");
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PREVENTALLOW test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PREVENTALLOW test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Set the PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
logging(LOG_VERBOSE, "Set the PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_REMOVAL_PREVENTED);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can still access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
logging(LOG_VERBOSE, "Verify we can still access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Create a second connection to the target");
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
logging(LOG_VERBOSE, "Create a second connection to the target");
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
logging(LOG_VERBOSE, "Try to eject the medium on the second connection");
|
||||
STARTSTOPUNIT(sd2, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Try to eject the medium on the second connection");
|
||||
STARTSTOPUNIT(sd2, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_REMOVAL_PREVENTED);
|
||||
|
||||
logging(LOG_VERBOSE, "Logout the second connection from target");
|
||||
mpath_sd2_put(sd2);
|
||||
logging(LOG_VERBOSE, "Logout the second connection from target");
|
||||
mpath_sd2_put(sd2);
|
||||
|
||||
logging(LOG_VERBOSE, "Clear PREVENT and load medium in case target failed");
|
||||
logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
logging(LOG_VERBOSE, "Clear PREVENT and load medium in case target failed");
|
||||
logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 1,
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 1,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
|
||||
@@ -30,56 +30,56 @@ test_preventallow_cold_reset(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_REMOVABLE;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_REMOVABLE;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that Target Warm Reset clears PREVENT MEDIUM REMOVAL");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that Target Warm Reset clears PREVENT MEDIUM REMOVAL");
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PREVENTALLOW test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PREVENTALLOW test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Set the PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
logging(LOG_VERBOSE, "Set the PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_REMOVAL_PREVENTED);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can still access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
logging(LOG_VERBOSE, "Verify we can still access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Perform cold reset on target");
|
||||
ret = iscsi_task_mgmt_target_cold_reset_sync(sd->iscsi_ctx);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Perform cold reset on target");
|
||||
ret = iscsi_task_mgmt_target_cold_reset_sync(sd->iscsi_ctx);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Wait until all unit attentions clear");
|
||||
while (testunitready(sd, EXPECT_STATUS_GOOD) != 0)
|
||||
;
|
||||
logging(LOG_VERBOSE, "Wait until all unit attentions clear");
|
||||
while (testunitready(sd, EXPECT_STATUS_GOOD) != 0)
|
||||
;
|
||||
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can not access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
logging(LOG_VERBOSE, "Verify we can not access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
EXPECT_NO_MEDIUM);
|
||||
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Clear PREVENT and load medium in case target failed");
|
||||
logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
logging(LOG_VERBOSE, "Clear PREVENT and load medium in case target failed");
|
||||
logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 1,
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 1,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
|
||||
@@ -28,45 +28,45 @@
|
||||
void
|
||||
test_preventallow_eject(void)
|
||||
{
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_REMOVABLE;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_REMOVABLE;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that we can not eject medium when PREVENT is active");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that we can not eject medium when PREVENT is active");
|
||||
|
||||
logging(LOG_VERBOSE, "Set the PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
logging(LOG_VERBOSE, "Set the PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_REMOVAL_PREVENTED);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can still access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
logging(LOG_VERBOSE, "Verify we can still access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can not access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
logging(LOG_VERBOSE, "Verify we can not access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
EXPECT_NO_MEDIUM);
|
||||
|
||||
logging(LOG_VERBOSE, "Set the PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
logging(LOG_VERBOSE, "Set the PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
|
||||
logging(LOG_VERBOSE, "Try to load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 1,
|
||||
logging(LOG_VERBOSE, "Try to load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 1,
|
||||
EXPECT_REMOVAL_PREVENTED);
|
||||
|
||||
logging(LOG_VERBOSE, "Clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
logging(LOG_VERBOSE, "Clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Load the medium again");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 1,
|
||||
logging(LOG_VERBOSE, "Load the medium again");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 1,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
|
||||
@@ -28,58 +28,58 @@
|
||||
void
|
||||
test_preventallow_itnexus_loss(void)
|
||||
{
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_REMOVABLE;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_REMOVABLE;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that IT-Nexus loss clears PREVENT MEDIUM REMOVAL");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that IT-Nexus loss clears PREVENT MEDIUM REMOVAL");
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PREVENTALLOW test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PREVENTALLOW test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Set the PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
logging(LOG_VERBOSE, "Set the PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_REMOVAL_PREVENTED);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can still access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
logging(LOG_VERBOSE, "Verify we can still access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Disconnect from the target.");
|
||||
iscsi_destroy_context(sd->iscsi_ctx);
|
||||
|
||||
logging(LOG_VERBOSE, "Disconnect from the target.");
|
||||
iscsi_destroy_context(sd->iscsi_ctx);
|
||||
|
||||
logging(LOG_VERBOSE, "Reconnect to target");
|
||||
sd->iscsi_ctx = iscsi_context_login(initiatorname1, sd->iscsi_url, &sd->iscsi_lun);
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
logging(LOG_VERBOSE, "Failed to login to target");
|
||||
return;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Reconnect to target");
|
||||
sd->iscsi_ctx = iscsi_context_login(initiatorname1, sd->iscsi_url, &sd->iscsi_lun);
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
logging(LOG_VERBOSE, "Failed to login to target");
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can not access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
logging(LOG_VERBOSE, "Verify we can not access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
EXPECT_NO_MEDIUM);
|
||||
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Clear PREVENT and load medium in case target failed");
|
||||
logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
logging(LOG_VERBOSE, "Clear PREVENT and load medium in case target failed");
|
||||
logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 1,
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 1,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
|
||||
@@ -28,59 +28,59 @@
|
||||
void
|
||||
test_preventallow_logout(void)
|
||||
{
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_REMOVABLE;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_REMOVABLE;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that Logout loss clears PREVENT MEDIUM REMOVAL");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that Logout loss clears PREVENT MEDIUM REMOVAL");
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PREVENTALLOW test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PREVENTALLOW test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Set the PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
logging(LOG_VERBOSE, "Set the PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_REMOVAL_PREVENTED);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can still access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
logging(LOG_VERBOSE, "Verify we can still access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Logout from target");
|
||||
iscsi_logout_sync(sd->iscsi_ctx);
|
||||
iscsi_destroy_context(sd->iscsi_ctx);
|
||||
logging(LOG_VERBOSE, "Logout from target");
|
||||
iscsi_logout_sync(sd->iscsi_ctx);
|
||||
iscsi_destroy_context(sd->iscsi_ctx);
|
||||
|
||||
logging(LOG_VERBOSE, "Relogin to target");
|
||||
sd->iscsi_ctx = iscsi_context_login(initiatorname1, sd->iscsi_url, &sd->iscsi_lun);
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
logging(LOG_VERBOSE, "Failed to login to target");
|
||||
return;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Relogin to target");
|
||||
sd->iscsi_ctx = iscsi_context_login(initiatorname1, sd->iscsi_url, &sd->iscsi_lun);
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
logging(LOG_VERBOSE, "Failed to login to target");
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can not access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
logging(LOG_VERBOSE, "Verify we can not access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
EXPECT_NO_MEDIUM);
|
||||
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Clear PREVENT and load medium in case target failed");
|
||||
logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
logging(LOG_VERBOSE, "Clear PREVENT and load medium in case target failed");
|
||||
logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 1,
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 1,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
|
||||
@@ -28,58 +28,58 @@
|
||||
void
|
||||
test_preventallow_lun_reset(void)
|
||||
{
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_REMOVABLE;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_REMOVABLE;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that Target Warm Reset clears PREVENT MEDIUM REMOVAL");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that Target Warm Reset clears PREVENT MEDIUM REMOVAL");
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PREVENTALLOW test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PREVENTALLOW test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Set the PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
logging(LOG_VERBOSE, "Set the PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_REMOVAL_PREVENTED);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can still access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
logging(LOG_VERBOSE, "Verify we can still access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Perform LUN reset on target");
|
||||
ret = iscsi_task_mgmt_lun_reset_sync(sd->iscsi_ctx, sd->iscsi_lun);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "Wait until all unit attentions clear");
|
||||
while (testunitready(sd, EXPECT_STATUS_GOOD) != 0)
|
||||
;
|
||||
|
||||
logging(LOG_VERBOSE, "Perform LUN reset on target");
|
||||
ret = iscsi_task_mgmt_lun_reset_sync(sd->iscsi_ctx, sd->iscsi_lun);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "Wait until all unit attentions clear");
|
||||
while (testunitready(sd, EXPECT_STATUS_GOOD) != 0)
|
||||
;
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can not access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
logging(LOG_VERBOSE, "Verify we can not access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
EXPECT_NO_MEDIUM);
|
||||
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Clear PREVENT and load medium in case target failed");
|
||||
logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
logging(LOG_VERBOSE, "Clear PREVENT and load medium in case target failed");
|
||||
logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 1,
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 1,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
|
||||
@@ -28,15 +28,15 @@
|
||||
void
|
||||
test_preventallow_simple(void)
|
||||
{
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_REMOVABLE;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_REMOVABLE;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREVENTALLOW basics");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test PREVENTALLOW basics");
|
||||
|
||||
logging(LOG_VERBOSE, "Test we can set PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
logging(LOG_VERBOSE, "Test we can set PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
|
||||
logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
}
|
||||
|
||||
@@ -28,58 +28,58 @@
|
||||
void
|
||||
test_preventallow_warm_reset(void)
|
||||
{
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_REMOVABLE;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_REMOVABLE;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that Target Warm Reset clears PREVENT MEDIUM REMOVAL");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that Target Warm Reset clears PREVENT MEDIUM REMOVAL");
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PREVENTALLOW test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PREVENTALLOW test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Set the PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
logging(LOG_VERBOSE, "Set the PREVENT flag");
|
||||
PREVENTALLOW(sd, 1);
|
||||
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_REMOVAL_PREVENTED);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can still access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
logging(LOG_VERBOSE, "Verify we can still access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Perform warm reset on target");
|
||||
ret = iscsi_task_mgmt_target_warm_reset_sync(sd->iscsi_ctx);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "Wait until all unit attentions clear");
|
||||
while (testunitready(sd, EXPECT_STATUS_GOOD) != 0)
|
||||
;
|
||||
|
||||
logging(LOG_VERBOSE, "Perform warm reset on target");
|
||||
ret = iscsi_task_mgmt_target_warm_reset_sync(sd->iscsi_ctx);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "Wait until all unit attentions clear");
|
||||
while (testunitready(sd, EXPECT_STATUS_GOOD) != 0)
|
||||
;
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Try to eject the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we can not access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
logging(LOG_VERBOSE, "Verify we can not access the media.");
|
||||
TESTUNITREADY(sd,
|
||||
EXPECT_NO_MEDIUM);
|
||||
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Clear PREVENT and load medium in case target failed");
|
||||
logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
logging(LOG_VERBOSE, "Clear PREVENT and load medium in case target failed");
|
||||
logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
|
||||
PREVENTALLOW(sd, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 1,
|
||||
logging(LOG_VERBOSE, "Load the medium");
|
||||
STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 1,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
|
||||
@@ -30,34 +30,34 @@
|
||||
void
|
||||
test_prin_read_keys_simple(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int al;
|
||||
int ret = 0;
|
||||
int al;
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test Persistent Reserve IN READ_KEYS works.");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test Persistent Reserve IN READ_KEYS works.");
|
||||
|
||||
ret = prin_read_keys(sd, &task, NULL);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTEN RESERVE IN is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE IN is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
ret = prin_read_keys(sd, &task, NULL);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTEN RESERVE IN is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE IN is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Test DATA-IN is at least 8 bytes.");
|
||||
if (task->datain.size < 8) {
|
||||
logging(LOG_NORMAL,
|
||||
"[FAILED] DATA-IN returned less than 8 bytes");
|
||||
return;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Test DATA-IN is at least 8 bytes.");
|
||||
if (task->datain.size < 8) {
|
||||
logging(LOG_NORMAL,
|
||||
"[FAILED] DATA-IN returned less than 8 bytes");
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test ADDITIONAL_LENGTH matches DATA_IN size.");
|
||||
al = scsi_get_uint32(&task->datain.data[4]);
|
||||
if (al != task->datain.size - 8) {
|
||||
logging(LOG_NORMAL,
|
||||
"[FAILED] ADDITIONAL_LENGTH was %d bytes but %d was expected.",
|
||||
al, task->datain.size - 8);
|
||||
return;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Test ADDITIONAL_LENGTH matches DATA_IN size.");
|
||||
al = scsi_get_uint32(&task->datain.data[4]);
|
||||
if (al != task->datain.size - 8) {
|
||||
logging(LOG_NORMAL,
|
||||
"[FAILED] ADDITIONAL_LENGTH was %d bytes but %d was expected.",
|
||||
al, task->datain.size - 8);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,89 +27,89 @@
|
||||
#include "iscsi-test-cu.h"
|
||||
|
||||
static struct test_prin_report_caps_types {
|
||||
enum scsi_persistent_reservation_type_mask mask;
|
||||
enum scsi_persistent_out_type op;
|
||||
enum scsi_persistent_reservation_type_mask mask;
|
||||
enum scsi_persistent_out_type op;
|
||||
} report_caps_types_array[] = {
|
||||
{ SCSI_PR_TYPE_MASK_WR_EX_AR,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_ALL_REGISTRANTS },
|
||||
{ SCSI_PR_TYPE_MASK_EX_AC_RO,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_REGISTRANTS_ONLY },
|
||||
{ SCSI_PR_TYPE_MASK_WR_EX_RO,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_REGISTRANTS_ONLY },
|
||||
{ SCSI_PR_TYPE_MASK_EX_AC,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS },
|
||||
{ SCSI_PR_TYPE_MASK_WR_EX,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE },
|
||||
{ SCSI_PR_TYPE_MASK_EX_AC_AR,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_ALL_REGISTRANTS },
|
||||
{ 0, 0 }
|
||||
{ SCSI_PR_TYPE_MASK_WR_EX_AR,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_ALL_REGISTRANTS },
|
||||
{ SCSI_PR_TYPE_MASK_EX_AC_RO,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_REGISTRANTS_ONLY },
|
||||
{ SCSI_PR_TYPE_MASK_WR_EX_RO,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_REGISTRANTS_ONLY },
|
||||
{ SCSI_PR_TYPE_MASK_EX_AC,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS },
|
||||
{ SCSI_PR_TYPE_MASK_WR_EX,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE },
|
||||
{ SCSI_PR_TYPE_MASK_EX_AC_AR,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_ALL_REGISTRANTS },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
void
|
||||
test_prin_report_caps_simple(void)
|
||||
{
|
||||
int ret = 0;
|
||||
const unsigned long long key = rand_key();
|
||||
struct scsi_task *tsk;
|
||||
struct scsi_persistent_reserve_in_report_capabilities *rcaps;
|
||||
struct test_prin_report_caps_types *type;
|
||||
int ret = 0;
|
||||
const unsigned long long key = rand_key();
|
||||
struct scsi_task *tsk;
|
||||
struct scsi_persistent_reserve_in_report_capabilities *rcaps;
|
||||
struct test_prin_report_caps_types *type;
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_DATALOSS;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE,
|
||||
"Test Persistent Reserve In REPORT CAPABILITIES works.");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE,
|
||||
"Test Persistent Reserve In REPORT CAPABILITIES works.");
|
||||
|
||||
/* register our reservation key with the target */
|
||||
ret = prout_register_and_ignore(sd, key);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTENT RESERVE OUT is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE OUT is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* register our reservation key with the target */
|
||||
ret = prout_register_and_ignore(sd, key);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTENT RESERVE OUT is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE OUT is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
ret = prin_report_caps(sd, &tsk, &rcaps);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
ret = prin_report_caps(sd, &tsk, &rcaps);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
logging(LOG_VERBOSE,
|
||||
"Checking PERSISTENT RESERVE IN REPORT CAPABILITIES fields.");
|
||||
CU_ASSERT_EQUAL(rcaps->length, 8);
|
||||
CU_ASSERT_TRUE(rcaps->allow_commands <= 5);
|
||||
CU_ASSERT_EQUAL(rcaps->persistent_reservation_type_mask
|
||||
& ~SCSI_PR_TYPE_MASK_ALL, 0);
|
||||
logging(LOG_VERBOSE,
|
||||
"Checking PERSISTENT RESERVE IN REPORT CAPABILITIES fields.");
|
||||
CU_ASSERT_EQUAL(rcaps->length, 8);
|
||||
CU_ASSERT_TRUE(rcaps->allow_commands <= 5);
|
||||
CU_ASSERT_EQUAL(rcaps->persistent_reservation_type_mask
|
||||
& ~SCSI_PR_TYPE_MASK_ALL, 0);
|
||||
|
||||
for (type = &report_caps_types_array[0]; type->mask != 0; type++) {
|
||||
if (!(rcaps->persistent_reservation_type_mask & type->mask)) {
|
||||
logging(LOG_NORMAL,
|
||||
"PERSISTENT RESERVE op 0x%x not supported",
|
||||
type->op);
|
||||
continue;
|
||||
}
|
||||
for (type = &report_caps_types_array[0]; type->mask != 0; type++) {
|
||||
if (!(rcaps->persistent_reservation_type_mask & type->mask)) {
|
||||
logging(LOG_NORMAL,
|
||||
"PERSISTENT RESERVE op 0x%x not supported",
|
||||
type->op);
|
||||
continue;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE,
|
||||
"PERSISTENT RESERVE OUT op 0x%x supported, testing",
|
||||
type->op);
|
||||
logging(LOG_VERBOSE,
|
||||
"PERSISTENT RESERVE OUT op 0x%x supported, testing",
|
||||
type->op);
|
||||
|
||||
/* reserve the target */
|
||||
ret = prout_reserve(sd, key, type->op);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* reserve the target */
|
||||
ret = prout_reserve(sd, key, type->op);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
/* verify target reservation */
|
||||
ret = prin_verify_reserved_as(sd,
|
||||
pr_type_is_all_registrants(type->op) ? 0 : key,
|
||||
type->op);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* verify target reservation */
|
||||
ret = prin_verify_reserved_as(sd,
|
||||
pr_type_is_all_registrants(type->op) ? 0 : key,
|
||||
type->op);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
/* release the target */
|
||||
ret = prout_release(sd, key, type->op);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
/* release the target */
|
||||
ret = prout_release(sd, key, type->op);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(tsk);
|
||||
rcaps = NULL; /* freed with tsk */
|
||||
scsi_free_scsi_task(tsk);
|
||||
rcaps = NULL; /* freed with tsk */
|
||||
|
||||
/* drop registration */
|
||||
ret = prout_register_key(sd, 0, key);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* drop registration */
|
||||
ret = prout_register_key(sd, 0, key);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
|
||||
@@ -30,31 +30,31 @@
|
||||
void
|
||||
test_prin_serviceaction_range(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test Persistent Reserve IN Serviceaction range.");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test Persistent Reserve IN Serviceaction range.");
|
||||
|
||||
/* verify PRIN/READ_KEYS works -- XXX redundant -- remove this? */
|
||||
ret = prin_read_keys(sd, &task, NULL);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTEN RESERVE IN is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE IN is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* verify PRIN/READ_KEYS works -- XXX redundant -- remove this? */
|
||||
ret = prin_read_keys(sd, &task, NULL);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTEN RESERVE IN is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE IN is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
/* verify that PRIN/SA={0,1,2,3} works ... */
|
||||
for (i = 0; i < 4; i++) {
|
||||
ret = prin_task(sd, i, 1);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
/* verify that PRIN/SA={0,1,2,3} works ... */
|
||||
for (i = 0; i < 4; i++) {
|
||||
ret = prin_task(sd, i, 1);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
|
||||
/* verify that PRIN/SA={4..0x20} fails ... */
|
||||
for (i = 4; i < 0x20; i++) {
|
||||
ret = prin_task(sd, i, 0);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
/* verify that PRIN/SA={4..0x20} fails ... */
|
||||
for (i = 4; i < 0x20; i++) {
|
||||
ret = prin_task(sd, i, 0);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,60 +29,60 @@
|
||||
void
|
||||
test_prout_clear_simple(void)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t old_gen;
|
||||
const unsigned long long key = rand_key();
|
||||
struct scsi_task *tsk;
|
||||
struct scsi_persistent_reserve_in_read_keys *rk;
|
||||
int ret = 0;
|
||||
uint32_t old_gen;
|
||||
const unsigned long long key = rand_key();
|
||||
struct scsi_task *tsk;
|
||||
struct scsi_persistent_reserve_in_read_keys *rk;
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_DATALOSS;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test Persistent Reserve OUT CLEAR works.");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test Persistent Reserve OUT CLEAR works.");
|
||||
|
||||
/* register our reservation key with the target */
|
||||
ret = prout_register_and_ignore(sd, key);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTENT RESERVE OUT is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE OUT is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* register our reservation key with the target */
|
||||
ret = prout_register_and_ignore(sd, key);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTENT RESERVE OUT is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE OUT is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
ret = prin_read_keys(sd, &tsk, &rk);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
ret = prin_read_keys(sd, &tsk, &rk);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
CU_ASSERT_NOT_EQUAL(rk->num_keys, 0);
|
||||
/* retain PR generation number to check for increments */
|
||||
old_gen = rk->prgeneration;
|
||||
CU_ASSERT_NOT_EQUAL(rk->num_keys, 0);
|
||||
/* retain PR generation number to check for increments */
|
||||
old_gen = rk->prgeneration;
|
||||
|
||||
scsi_free_scsi_task(tsk);
|
||||
rk = NULL; /* freed with tsk */
|
||||
scsi_free_scsi_task(tsk);
|
||||
rk = NULL; /* freed with tsk */
|
||||
|
||||
/* reserve the target */
|
||||
ret = prout_reserve(sd, key,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* reserve the target */
|
||||
ret = prout_reserve(sd, key,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
/* verify target reservation */
|
||||
ret = prin_verify_reserved_as(sd, key,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* verify target reservation */
|
||||
ret = prin_verify_reserved_as(sd, key,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
/* clear reservation and registration */
|
||||
ret = prout_clear(sd, key);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* clear reservation and registration */
|
||||
ret = prout_clear(sd, key);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
ret = prin_verify_not_reserved(sd);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
ret = prin_verify_not_reserved(sd);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
ret = prin_read_keys(sd, &tsk, &rk);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
ret = prin_read_keys(sd, &tsk, &rk);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
CU_ASSERT_EQUAL(rk->num_keys, 0);
|
||||
/* generation incremented once for CLEAR (not for RESERVE) */
|
||||
CU_ASSERT_EQUAL(rk->prgeneration, old_gen + 1);
|
||||
CU_ASSERT_EQUAL(rk->num_keys, 0);
|
||||
/* generation incremented once for CLEAR (not for RESERVE) */
|
||||
CU_ASSERT_EQUAL(rk->prgeneration, old_gen + 1);
|
||||
|
||||
scsi_free_scsi_task(tsk);
|
||||
rk = NULL; /* freed with tsk */
|
||||
scsi_free_scsi_task(tsk);
|
||||
rk = NULL; /* freed with tsk */
|
||||
}
|
||||
|
||||
@@ -30,86 +30,86 @@
|
||||
void
|
||||
test_prout_preempt_rm_reg(void)
|
||||
{
|
||||
int ret = 0;
|
||||
const unsigned long long k1 = rand_key();
|
||||
const unsigned long long k2 = rand_key();
|
||||
struct scsi_device *sd2;
|
||||
struct scsi_task *tsk;
|
||||
uint32_t old_gen;
|
||||
int num_uas;
|
||||
struct scsi_persistent_reserve_in_read_keys *rk;
|
||||
int ret = 0;
|
||||
const unsigned long long k1 = rand_key();
|
||||
const unsigned long long k2 = rand_key();
|
||||
struct scsi_device *sd2;
|
||||
struct scsi_task *tsk;
|
||||
uint32_t old_gen;
|
||||
int num_uas;
|
||||
struct scsi_persistent_reserve_in_read_keys *rk;
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_DATALOSS;
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test Persistent Reserve IN PREEMPT works.");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test Persistent Reserve IN PREEMPT works.");
|
||||
|
||||
ret = prout_register_and_ignore(sd, k1);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTEN RESERVE OUT is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE OUT is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
ret = prout_register_and_ignore(sd, k1);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTEN RESERVE OUT is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE OUT is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
/* clear all PR state */
|
||||
ret = prout_clear(sd, k1);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* clear all PR state */
|
||||
ret = prout_clear(sd, k1);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
/* need to reregister cleared key */
|
||||
ret = prout_register_and_ignore(sd, k1);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* need to reregister cleared key */
|
||||
ret = prout_register_and_ignore(sd, k1);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
if (ret < 0)
|
||||
return;
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
/* register secondary key */
|
||||
ret = prout_register_and_ignore(sd2, k2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* register secondary key */
|
||||
ret = prout_register_and_ignore(sd2, k2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
/* confirm that k1 and k2 are registered */
|
||||
ret = prin_read_keys(sd, &tsk, &rk);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, 0);
|
||||
/* confirm that k1 and k2 are registered */
|
||||
ret = prin_read_keys(sd, &tsk, &rk);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, 0);
|
||||
|
||||
CU_ASSERT_EQUAL(rk->num_keys, 2);
|
||||
/* retain PR generation number to check for increments */
|
||||
old_gen = rk->prgeneration;
|
||||
CU_ASSERT_EQUAL(rk->num_keys, 2);
|
||||
/* retain PR generation number to check for increments */
|
||||
old_gen = rk->prgeneration;
|
||||
|
||||
scsi_free_scsi_task(tsk);
|
||||
rk = NULL; /* freed with tsk */
|
||||
scsi_free_scsi_task(tsk);
|
||||
rk = NULL; /* freed with tsk */
|
||||
|
||||
/* use second connection to clear k1 registration */
|
||||
ret = prout_preempt(sd2, k1, k2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* use second connection to clear k1 registration */
|
||||
ret = prout_preempt(sd2, k1, k2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
/* clear any UAs generated by preempt */
|
||||
ret = test_iscsi_tur_until_good(sd, &num_uas);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
ret = test_iscsi_tur_until_good(sd2, &num_uas);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* clear any UAs generated by preempt */
|
||||
ret = test_iscsi_tur_until_good(sd, &num_uas);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
ret = test_iscsi_tur_until_good(sd2, &num_uas);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
ret = prin_read_keys(sd, &tsk, &rk);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, 0);
|
||||
ret = prin_read_keys(sd, &tsk, &rk);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, 0);
|
||||
|
||||
CU_ASSERT_EQUAL(rk->num_keys, 1);
|
||||
/* ensure preempt bumped generation number */
|
||||
CU_ASSERT_EQUAL(rk->prgeneration, old_gen + 1);
|
||||
/* ensure k2 is retained */
|
||||
CU_ASSERT_EQUAL(rk->keys[0], k2);
|
||||
CU_ASSERT_EQUAL(rk->num_keys, 1);
|
||||
/* ensure preempt bumped generation number */
|
||||
CU_ASSERT_EQUAL(rk->prgeneration, old_gen + 1);
|
||||
/* ensure k2 is retained */
|
||||
CU_ASSERT_EQUAL(rk->keys[0], k2);
|
||||
|
||||
/* unregister k2 */
|
||||
ret = prout_register_key(sd2, 0, k2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* unregister k2 */
|
||||
ret = prout_register_key(sd2, 0, k2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
|
||||
@@ -30,35 +30,35 @@
|
||||
void
|
||||
test_prout_register_simple(void)
|
||||
{
|
||||
const unsigned long long key = rand_key();
|
||||
int ret = 0;
|
||||
const unsigned long long key = rand_key();
|
||||
int ret = 0;
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test Persistent Reserve IN REGISTER works.");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test Persistent Reserve IN REGISTER works.");
|
||||
|
||||
/* register our reservation key with the target */
|
||||
ret = prout_register_and_ignore(sd, key);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTEN RESERVE OUT is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE OUT is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* register our reservation key with the target */
|
||||
ret = prout_register_and_ignore(sd, key);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTEN RESERVE OUT is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE OUT is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
/* verify we can read the registration */
|
||||
ret = prin_verify_key_presence(sd, key, 1);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* verify we can read the registration */
|
||||
ret = prin_verify_key_presence(sd, key, 1);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
/* try to reregister, which should fail */
|
||||
ret = prout_reregister_key_fails(sd, key+1);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* try to reregister, which should fail */
|
||||
ret = prout_reregister_key_fails(sd, key+1);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
/* release from the target */
|
||||
ret = prout_register_key(sd, 0, key);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* release from the target */
|
||||
ret = prout_register_key(sd, 0, key);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
/* Verify the registration is gone */
|
||||
ret = prin_verify_key_presence(sd, key, 0);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* Verify the registration is gone */
|
||||
ret = prin_verify_key_presence(sd, key, 0);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
|
||||
@@ -33,232 +33,232 @@ verify_persistent_reserve_access(struct scsi_device *sd1, struct scsi_device *sd
|
||||
int unreg_i2_can_read,
|
||||
int unreg_i2_can_write)
|
||||
{
|
||||
int ret;
|
||||
const unsigned long long key = rand_key();
|
||||
const unsigned long long key2 = rand_key();
|
||||
int ret;
|
||||
const unsigned long long key = rand_key();
|
||||
const unsigned long long key2 = rand_key();
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE,
|
||||
"Verify access for reservation type: %s",
|
||||
scsi_pr_type_str(pr_type));
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE,
|
||||
"Verify access for reservation type: %s",
|
||||
scsi_pr_type_str(pr_type));
|
||||
|
||||
/* send TURs to clear possible check conditions */
|
||||
(void) testunitready_clear_ua(sd1);
|
||||
(void) testunitready_clear_ua(sd2);
|
||||
/* send TURs to clear possible check conditions */
|
||||
(void) testunitready_clear_ua(sd1);
|
||||
(void) testunitready_clear_ua(sd2);
|
||||
|
||||
/* register our reservation key with the target */
|
||||
ret = prout_register_and_ignore(sd1, key);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTEN RESERVE OUT is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE OUT is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
ret = prout_register_and_ignore(sd2, key2);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* register our reservation key with the target */
|
||||
ret = prout_register_and_ignore(sd1, key);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTEN RESERVE OUT is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE OUT is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
ret = prout_register_and_ignore(sd2, key2);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
/* reserve the target through initiator 1 */
|
||||
ret = prout_reserve(sd1, key, pr_type);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* reserve the target through initiator 1 */
|
||||
ret = prout_reserve(sd1, key, pr_type);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
/* verify target reservation */
|
||||
ret = prin_verify_reserved_as(sd1,
|
||||
pr_type_is_all_registrants(pr_type) ? 0 : key,
|
||||
pr_type);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* verify target reservation */
|
||||
ret = prin_verify_reserved_as(sd1,
|
||||
pr_type_is_all_registrants(pr_type) ? 0 : key,
|
||||
pr_type);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(scratch);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(scratch);
|
||||
|
||||
/* make sure init1 can read */
|
||||
ret = verify_read_works(sd1, scratch);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* make sure init1 can read */
|
||||
ret = verify_read_works(sd1, scratch);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
/* make sure init1 can write */
|
||||
ret = verify_write_works(sd1, scratch);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* make sure init1 can write */
|
||||
ret = verify_write_works(sd1, scratch);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
/* verify registered init2 read access */
|
||||
if (reg_i2_can_read)
|
||||
ret = verify_read_works(sd2, scratch);
|
||||
else
|
||||
ret = verify_read_fails(sd2, scratch);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* verify registered init2 read access */
|
||||
if (reg_i2_can_read)
|
||||
ret = verify_read_works(sd2, scratch);
|
||||
else
|
||||
ret = verify_read_fails(sd2, scratch);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
/* verify registered init2 write access */
|
||||
if (reg_i2_can_write)
|
||||
ret = verify_write_works(sd2, scratch);
|
||||
else
|
||||
ret = verify_write_fails(sd2, scratch);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* verify registered init2 write access */
|
||||
if (reg_i2_can_write)
|
||||
ret = verify_write_works(sd2, scratch);
|
||||
else
|
||||
ret = verify_write_fails(sd2, scratch);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
/* unregister init2 */
|
||||
ret = prout_register_key(sd2, 0, key2);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* unregister init2 */
|
||||
ret = prout_register_key(sd2, 0, key2);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
/* verify unregistered init2 read access */
|
||||
if (unreg_i2_can_read)
|
||||
ret = verify_read_works(sd2, scratch);
|
||||
else
|
||||
ret = verify_read_fails(sd2, scratch);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* verify unregistered init2 read access */
|
||||
if (unreg_i2_can_read)
|
||||
ret = verify_read_works(sd2, scratch);
|
||||
else
|
||||
ret = verify_read_fails(sd2, scratch);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
/* verify unregistered init2 write access */
|
||||
if (unreg_i2_can_write)
|
||||
ret = verify_write_works(sd2, scratch);
|
||||
else
|
||||
ret = verify_write_fails(sd2, scratch);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* verify unregistered init2 write access */
|
||||
if (unreg_i2_can_write)
|
||||
ret = verify_write_works(sd2, scratch);
|
||||
else
|
||||
ret = verify_write_fails(sd2, scratch);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
/* release our reservation */
|
||||
ret = prout_release(sd1, key, pr_type);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* release our reservation */
|
||||
ret = prout_release(sd1, key, pr_type);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
/* remove our key from the target */
|
||||
ret = prout_register_key(sd1, 0, key);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* remove our key from the target */
|
||||
ret = prout_register_key(sd1, 0, key);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
}
|
||||
|
||||
void
|
||||
test_prout_reserve_access_ea(void)
|
||||
{
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_access(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS,
|
||||
0, 0, 0, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_access(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS,
|
||||
0, 0, 0, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
}
|
||||
|
||||
void
|
||||
test_prout_reserve_access_we(void)
|
||||
{
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_access(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE,
|
||||
1, 0, 1, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_access(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE,
|
||||
1, 0, 1, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
}
|
||||
|
||||
void
|
||||
test_prout_reserve_access_earo(void)
|
||||
{
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_access(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_REGISTRANTS_ONLY,
|
||||
1, 1, 0, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_access(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_REGISTRANTS_ONLY,
|
||||
1, 1, 0, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
}
|
||||
|
||||
void
|
||||
test_prout_reserve_access_wero(void)
|
||||
{
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_access(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_REGISTRANTS_ONLY,
|
||||
1, 1, 1, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_access(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_REGISTRANTS_ONLY,
|
||||
1, 1, 1, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
}
|
||||
|
||||
void
|
||||
test_prout_reserve_access_eaar(void)
|
||||
{
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_access(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_ALL_REGISTRANTS,
|
||||
1, 1, 0, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_access(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_ALL_REGISTRANTS,
|
||||
1, 1, 0, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
}
|
||||
|
||||
void
|
||||
test_prout_reserve_access_wear(void)
|
||||
{
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_access(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_ALL_REGISTRANTS,
|
||||
1, 1, 1, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_access(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_ALL_REGISTRANTS,
|
||||
1, 1, 1, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
}
|
||||
|
||||
@@ -30,204 +30,204 @@ verify_persistent_reserve_ownership(struct scsi_device *sd1, struct scsi_device
|
||||
const enum scsi_persistent_out_type pr_type,
|
||||
int resvn_is_shared)
|
||||
{
|
||||
int ret;
|
||||
const unsigned long long key1 = rand_key();
|
||||
const unsigned long long key2 = rand_key();
|
||||
int ret;
|
||||
const unsigned long long key1 = rand_key();
|
||||
const unsigned long long key2 = rand_key();
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE,
|
||||
"Verify ownership for reservation type: %s",
|
||||
scsi_pr_type_str(pr_type));
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE,
|
||||
"Verify ownership for reservation type: %s",
|
||||
scsi_pr_type_str(pr_type));
|
||||
|
||||
/* send TURs to clear possible check conditions */
|
||||
(void) testunitready_clear_ua(sd1);
|
||||
(void) testunitready_clear_ua(sd2);
|
||||
/* send TURs to clear possible check conditions */
|
||||
(void) testunitready_clear_ua(sd1);
|
||||
(void) testunitready_clear_ua(sd2);
|
||||
|
||||
/* register our reservation key with the target */
|
||||
ret = prout_register_and_ignore(sd1, key1);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTEN RESERVE OUT is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE OUT is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
ret = prout_register_and_ignore(sd2, key2);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* register our reservation key with the target */
|
||||
ret = prout_register_and_ignore(sd1, key1);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTEN RESERVE OUT is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE OUT is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
ret = prout_register_and_ignore(sd2, key2);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
/* reserve the target through initiator 1 */
|
||||
ret = prout_reserve(sd1, key1, pr_type);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* reserve the target through initiator 1 */
|
||||
ret = prout_reserve(sd1, key1, pr_type);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
/* verify target reservation */
|
||||
ret = prin_verify_reserved_as(sd1,
|
||||
pr_type_is_all_registrants(pr_type) ? 0 : key1,
|
||||
pr_type);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* verify target reservation */
|
||||
ret = prin_verify_reserved_as(sd1,
|
||||
pr_type_is_all_registrants(pr_type) ? 0 : key1,
|
||||
pr_type);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
/* unregister init1 */
|
||||
ret = prout_register_key(sd1, 0, key1);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* unregister init1 */
|
||||
ret = prout_register_key(sd1, 0, key1);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
/* verify if reservation is still present */
|
||||
if (resvn_is_shared) {
|
||||
/* verify target reservation */
|
||||
ret = prin_verify_reserved_as(sd1,
|
||||
pr_type_is_all_registrants(pr_type) ? 0 : key1,
|
||||
pr_type);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* verify if reservation is still present */
|
||||
if (resvn_is_shared) {
|
||||
/* verify target reservation */
|
||||
ret = prin_verify_reserved_as(sd1,
|
||||
pr_type_is_all_registrants(pr_type) ? 0 : key1,
|
||||
pr_type);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
/* release our reservation */
|
||||
ret = prout_release(sd2, key2, pr_type);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
} else {
|
||||
/* verify target is not reserved now */
|
||||
ret = prin_verify_not_reserved(sd1);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* release our reservation */
|
||||
ret = prout_release(sd2, key2, pr_type);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
} else {
|
||||
/* verify target is not reserved now */
|
||||
ret = prin_verify_not_reserved(sd1);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
|
||||
/* send TUR to clear possible check condition */
|
||||
(void) testunitready_clear_ua(sd2);
|
||||
}
|
||||
/* send TUR to clear possible check condition */
|
||||
(void) testunitready_clear_ua(sd2);
|
||||
}
|
||||
|
||||
/* remove our remaining key from the target */
|
||||
ret = prout_register_key(sd2, 0, key2);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
/* remove our remaining key from the target */
|
||||
ret = prout_register_key(sd2, 0, key2);
|
||||
CU_ASSERT_EQUAL(0, ret);
|
||||
}
|
||||
|
||||
void
|
||||
test_prout_reserve_ownership_ea(void)
|
||||
{
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_ownership(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_ownership(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
}
|
||||
|
||||
void
|
||||
test_prout_reserve_ownership_we(void)
|
||||
{
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_ownership(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_ownership(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
}
|
||||
|
||||
void
|
||||
test_prout_reserve_ownership_earo(void)
|
||||
{
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_ownership(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_REGISTRANTS_ONLY, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_ownership(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_REGISTRANTS_ONLY, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
}
|
||||
|
||||
void
|
||||
test_prout_reserve_ownership_wero(void)
|
||||
{
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_ownership(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_REGISTRANTS_ONLY, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_ownership(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_REGISTRANTS_ONLY, 0);
|
||||
mpath_sd2_put(sd2);
|
||||
}
|
||||
|
||||
void
|
||||
test_prout_reserve_ownership_eaar(void)
|
||||
{
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_ownership(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_ALL_REGISTRANTS, 1);
|
||||
mpath_sd2_put(sd2);
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_ownership(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_ALL_REGISTRANTS, 1);
|
||||
mpath_sd2_put(sd2);
|
||||
}
|
||||
|
||||
void
|
||||
test_prout_reserve_ownership_wear(void)
|
||||
{
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
struct scsi_device *sd2;
|
||||
int ret;
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This PERSISTENT RESERVE test is "
|
||||
"only supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_ownership(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_ALL_REGISTRANTS, 1);
|
||||
mpath_sd2_put(sd2);
|
||||
ret = mpath_sd2_get_or_clone(sd, &sd2);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
verify_persistent_reserve_ownership(sd, sd2,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_ALL_REGISTRANTS, 1);
|
||||
mpath_sd2_put(sd2);
|
||||
}
|
||||
|
||||
@@ -31,57 +31,57 @@
|
||||
* list of persistent reservation types to test, in order
|
||||
*/
|
||||
static enum scsi_persistent_out_type pr_types_to_test[] = {
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_REGISTRANTS_ONLY,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_REGISTRANTS_ONLY,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_ALL_REGISTRANTS,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_ALL_REGISTRANTS,
|
||||
0
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_REGISTRANTS_ONLY,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_REGISTRANTS_ONLY,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_ALL_REGISTRANTS,
|
||||
SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_ALL_REGISTRANTS,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
test_prout_reserve_simple(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
const unsigned long long key = rand_key();
|
||||
int ret = 0;
|
||||
int i;
|
||||
const unsigned long long key = rand_key();
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test Persistent Reserve IN RESERVE works.");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test Persistent Reserve IN RESERVE works.");
|
||||
|
||||
/* register our reservation key with the target */
|
||||
ret = prout_register_and_ignore(sd, key);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTEN RESERVE OUT is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE OUT is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* register our reservation key with the target */
|
||||
ret = prout_register_and_ignore(sd, key);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] PERSISTEN RESERVE OUT is not implemented.");
|
||||
CU_PASS("PERSISTENT RESERVE OUT is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
/* test each reservatoin type */
|
||||
for (i = 0; pr_types_to_test[i] != 0; i++) {
|
||||
enum scsi_persistent_out_type pr_type = pr_types_to_test[i];
|
||||
/* test each reservatoin type */
|
||||
for (i = 0; pr_types_to_test[i] != 0; i++) {
|
||||
enum scsi_persistent_out_type pr_type = pr_types_to_test[i];
|
||||
|
||||
/* reserve the target */
|
||||
ret = prout_reserve(sd, key, pr_type);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* reserve the target */
|
||||
ret = prout_reserve(sd, key, pr_type);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
/* verify target reservation */
|
||||
ret = prin_verify_reserved_as(sd,
|
||||
pr_type_is_all_registrants(pr_type) ? 0 : key,
|
||||
pr_type);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* verify target reservation */
|
||||
ret = prin_verify_reserved_as(sd,
|
||||
pr_type_is_all_registrants(pr_type) ? 0 : key,
|
||||
pr_type);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
/* release our reservation */
|
||||
ret = prout_release(sd, key, pr_type);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
/* release our reservation */
|
||||
ret = prout_release(sd, key, pr_type);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
|
||||
/* remove our key from the target */
|
||||
ret = prout_register_key(sd, 0, key);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
/* remove our key from the target */
|
||||
ret = prout_register_key(sd, 0, key);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
|
||||
}
|
||||
|
||||
@@ -27,26 +27,26 @@
|
||||
void
|
||||
test_read10_0blocks(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ10 0-blocks at LBA==0");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ10 0-blocks at LBA==0");
|
||||
|
||||
READ10(sd, NULL, 0, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
READ10(sd, NULL, 0, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
if (num_blocks > 0x80000000) {
|
||||
CU_PASS("[SKIPPED] LUN is too big");
|
||||
return;
|
||||
}
|
||||
if (num_blocks > 0x80000000) {
|
||||
CU_PASS("[SKIPPED] LUN is too big");
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ10 0-blocks one block past end-of-LUN");
|
||||
READ10(sd, NULL, num_blocks + 1, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, "Test READ10 0-blocks one block past end-of-LUN");
|
||||
READ10(sd, NULL, num_blocks + 1, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ10 0-blocks at LBA==2^31");
|
||||
READ10(sd, NULL, 0x80000000, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, "Test READ10 0-blocks at LBA==2^31");
|
||||
READ10(sd, NULL, 0x80000000, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ10 0-blocks at LBA==-1");
|
||||
READ10(sd, NULL, -1, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, "Test READ10 0-blocks at LBA==-1");
|
||||
READ10(sd, NULL, -1, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
|
||||
@@ -28,51 +28,51 @@
|
||||
void
|
||||
test_read10_beyond_eol(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if (num_blocks >= 0x80000000) {
|
||||
CU_PASS("LUN is too big for read-beyond-eol tests with READ10. Skipping test.\n");
|
||||
return;
|
||||
}
|
||||
if (num_blocks >= 0x80000000) {
|
||||
CU_PASS("LUN is too big for read-beyond-eol tests with READ10. Skipping test.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ10 1-256 blocks one block beyond the end");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ10(sd, NULL, num_blocks + 1 - i,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ10 1-256 blocks one block beyond the end");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ10(sd, NULL, num_blocks + 1 - i,
|
||||
i * block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ10 1-256 blocks at LBA==2^31");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ10(sd, NULL, 0x80000000,
|
||||
logging(LOG_VERBOSE, "Test READ10 1-256 blocks at LBA==2^31");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ10(sd, NULL, 0x80000000,
|
||||
i * block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ10 1-256 blocks at LBA==-1");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ10(sd, NULL, -1, i * block_size,
|
||||
logging(LOG_VERBOSE, "Test READ10 1-256 blocks at LBA==-1");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ10(sd, NULL, -1, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ10 2-256 blocks all but one block beyond the end");
|
||||
for (i = 2; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ10(sd, NULL, num_blocks - 1,
|
||||
logging(LOG_VERBOSE, "Test READ10 2-256 blocks all but one block beyond the end");
|
||||
for (i = 2; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ10(sd, NULL, num_blocks - 1,
|
||||
i * block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,80 +29,80 @@
|
||||
void
|
||||
test_read10_dpofua(void)
|
||||
{
|
||||
int dpofua, usage_data_dpofua;
|
||||
struct scsi_task *ms_task = NULL;
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_task *rso_task = NULL;
|
||||
struct scsi_report_supported_op_codes_one_command *rsoc;
|
||||
int dpofua, usage_data_dpofua;
|
||||
struct scsi_task *ms_task = NULL;
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_task *rso_task = NULL;
|
||||
struct scsi_report_supported_op_codes_one_command *rsoc;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ10 DPO/FUA flags");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ10 DPO/FUA flags");
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
logging(LOG_VERBOSE, "Read the DPOFUA flag from mode sense data");
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
logging(LOG_VERBOSE, "Read the DPOFUA flag from mode sense data");
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode sense returned status GOOD");
|
||||
ms = scsi_datain_unmarshall(ms_task);
|
||||
dpofua = ms && (ms->device_specific_parameter & 0x10);
|
||||
scsi_free_scsi_task(ms_task);
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode sense returned status GOOD");
|
||||
ms = scsi_datain_unmarshall(ms_task);
|
||||
dpofua = ms && (ms->device_specific_parameter & 0x10);
|
||||
scsi_free_scsi_task(ms_task);
|
||||
|
||||
if (dpofua) {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is set. Device should allow "
|
||||
"DPO/FUA flags in CDBs");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is clear. Device should fail "
|
||||
"CDBs with DPO/FUA set");
|
||||
}
|
||||
if (dpofua) {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is set. Device should allow "
|
||||
"DPO/FUA flags in CDBs");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is clear. Device should fail "
|
||||
"CDBs with DPO/FUA set");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ10 with DPO==1");
|
||||
if (dpofua) {
|
||||
READ10(sd, NULL, 0,
|
||||
logging(LOG_VERBOSE, "Test READ10 with DPO==1");
|
||||
if (dpofua) {
|
||||
READ10(sd, NULL, 0,
|
||||
block_size, block_size, 0, 1, 0, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
} else {
|
||||
READ10(sd, NULL, 0,
|
||||
} else {
|
||||
READ10(sd, NULL, 0,
|
||||
block_size, block_size, 0, 1, 0, 0, 0, NULL,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ10 with FUA==1");
|
||||
if (dpofua) {
|
||||
READ10(sd, NULL, 0,
|
||||
logging(LOG_VERBOSE, "Test READ10 with FUA==1");
|
||||
if (dpofua) {
|
||||
READ10(sd, NULL, 0,
|
||||
block_size, block_size, 0, 0, 1, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
} else {
|
||||
READ10(sd, NULL, 0,
|
||||
} else {
|
||||
READ10(sd, NULL, 0,
|
||||
block_size, block_size, 0, 0, 1, 0, 0, NULL,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ10 with DPO==1 FUA==1");
|
||||
if (dpofua) {
|
||||
READ10(sd, NULL, 0,
|
||||
logging(LOG_VERBOSE, "Test READ10 with DPO==1 FUA==1");
|
||||
if (dpofua) {
|
||||
READ10(sd, NULL, 0,
|
||||
block_size, block_size, 0, 1, 1, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
} else {
|
||||
READ10(sd, NULL, 0,
|
||||
} else {
|
||||
READ10(sd, NULL, 0,
|
||||
block_size, block_size, 0, 1, 1, 0, 0, NULL,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try fetching REPORT_SUPPORTED_OPCODES "
|
||||
"for READ10");
|
||||
REPORT_SUPPORTED_OPCODES(sd, &rso_task,
|
||||
logging(LOG_VERBOSE, "Try fetching REPORT_SUPPORTED_OPCODES "
|
||||
"for READ10");
|
||||
REPORT_SUPPORTED_OPCODES(sd, &rso_task,
|
||||
0, SCSI_REPORT_SUPPORTING_OPCODE,
|
||||
SCSI_OPCODE_READ10,
|
||||
0,
|
||||
65535,
|
||||
EXPECT_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc);
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc);
|
||||
|
||||
usage_data_dpofua = rsoc->cdb_usage_data[1] & 0x18;
|
||||
if (dpofua) {
|
||||
@@ -123,5 +123,5 @@ test_read10_dpofua(void)
|
||||
}
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(rso_task);
|
||||
scsi_free_scsi_task(rso_task);
|
||||
}
|
||||
|
||||
@@ -32,236 +32,236 @@
|
||||
void
|
||||
test_read10_invalid(void)
|
||||
{
|
||||
struct iscsi_data data;
|
||||
struct scsi_task *task_ret;
|
||||
struct iscsi_data data;
|
||||
struct scsi_task *task_ret;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test invalid READ10 commands");
|
||||
logging(LOG_VERBOSE, "Block size is %zu", block_size);
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test invalid READ10 commands");
|
||||
logging(LOG_VERBOSE, "Block size is %zu", block_size);
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This READ10 test is only "
|
||||
"supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This READ10 test is only "
|
||||
"supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try a read10 of 1 block but xferlength == 0 */
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
/* Try a read10 of 1 block but xferlength == 0 */
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 1;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 0;
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 1;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 0;
|
||||
|
||||
/*
|
||||
* we don't want autoreconnect since some targets will drop the session
|
||||
* on this condition.
|
||||
*/
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
/*
|
||||
* we don't want autoreconnect since some targets will drop the session
|
||||
* on this condition.
|
||||
*/
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==0");
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==0");
|
||||
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
CU_ASSERT_NOT_EQUAL(task->status, SCSI_STATUS_CANCELLED); /* XXX redundant? */
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
CU_ASSERT_NOT_EQUAL(task->status, SCSI_STATUS_CANCELLED); /* XXX redundant? */
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
|
||||
block_size);
|
||||
if (task->residual != block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
|
||||
block_size);
|
||||
if (task->residual != block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
/* in case the previous test failed the session */
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
/* in case the previous test failed the session */
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==10000");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==10000");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 1;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 10000;
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 1;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 10000;
|
||||
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got a whole block back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)block_size);
|
||||
logging(LOG_VERBOSE, "Verify we got a whole block back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)block_size);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify residual underflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"underflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW);
|
||||
logging(LOG_VERBOSE, "Verify residual underflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"underflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual underflow",
|
||||
10000 - block_size);
|
||||
if (task->residual != 10000 - block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
10000 - block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, 10000 - block_size);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual underflow",
|
||||
10000 - block_size);
|
||||
if (task->residual != 10000 - block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
10000 - block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, 10000 - block_size);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==200");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==200");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 1;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 200;
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 1;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 200;
|
||||
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got 200 bytes back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, 200);
|
||||
logging(LOG_VERBOSE, "Verify we got 200 bytes back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, 200);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
|
||||
block_size - 200);
|
||||
if (task->residual != block_size - 200) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size - 200, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size - 200);
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
|
||||
block_size - 200);
|
||||
if (task->residual != block_size - 200) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size - 200, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size - 200);
|
||||
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try reading two blocks but iSCSI expected "
|
||||
"transfer length==%zu (==one block)", block_size);
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
logging(LOG_VERBOSE, "Try reading two blocks but iSCSI expected "
|
||||
"transfer length==%zu (==one block)", block_size);
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 2;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = block_size;
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 2;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = block_size;
|
||||
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got one whole block back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)block_size);
|
||||
logging(LOG_VERBOSE, "Verify we got one whole block back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)block_size);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got one block of residual overflow");
|
||||
if (task->residual != block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size);
|
||||
logging(LOG_VERBOSE, "Verify we got one block of residual overflow");
|
||||
if (task->residual != block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size);
|
||||
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try READ10 for one block but flag it as a write on the iSCSI layer.");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
logging(LOG_VERBOSE, "Try READ10 for one block but flag it as a write on the iSCSI layer.");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 1;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_WRITE;
|
||||
task->expxferlen = block_size;
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 1;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_WRITE;
|
||||
task->expxferlen = block_size;
|
||||
|
||||
memset(scratch, 0xa6, block_size);
|
||||
data.size = block_size;
|
||||
data.data = (unsigned char *)scratch;
|
||||
memset(scratch, 0xa6, block_size);
|
||||
data.size = block_size;
|
||||
data.data = (unsigned char *)scratch;
|
||||
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
iscsi_set_timeout(sd->iscsi_ctx, 3);
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data);
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
iscsi_set_timeout(sd->iscsi_ctx, 3);
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data);
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
}
|
||||
|
||||
@@ -29,25 +29,25 @@
|
||||
void
|
||||
test_read10_rdprotect(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Try out different non-zero values for RDPROTECT.
|
||||
*/
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ10 with non-zero RDPROTECT");
|
||||
/*
|
||||
* Try out different non-zero values for RDPROTECT.
|
||||
*/
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ10 with non-zero RDPROTECT");
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
if (!inq->protect || (rc16 != NULL && !rc16->prot_en)) {
|
||||
logging(LOG_VERBOSE, "Device does not support/use protection information. All commands should fail.");
|
||||
for (i = 1; i < 8; i++) {
|
||||
READ10(sd, NULL, 0, block_size, block_size,
|
||||
if (!inq->protect || (rc16 != NULL && !rc16->prot_en)) {
|
||||
logging(LOG_VERBOSE, "Device does not support/use protection information. All commands should fail.");
|
||||
for (i = 1; i < 8; i++) {
|
||||
READ10(sd, NULL, 0, block_size, block_size,
|
||||
i, 0, 0, 0, 0, NULL,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_NORMAL, "No tests for devices that support protection information yet.");
|
||||
logging(LOG_NORMAL, "No tests for devices that support protection information yet.");
|
||||
}
|
||||
|
||||
@@ -35,206 +35,206 @@
|
||||
void
|
||||
test_read10_residuals(void)
|
||||
{
|
||||
struct scsi_task *task_ret;
|
||||
struct scsi_task *task_ret;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ10 commands with residuals");
|
||||
logging(LOG_VERBOSE, "Block size is %zu", block_size);
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ10 commands with residuals");
|
||||
logging(LOG_VERBOSE, "Block size is %zu", block_size);
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This READ10 test is only "
|
||||
"supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This READ10 test is only "
|
||||
"supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try a read10 of 1 block but xferlength == 0 */
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
/* Try a read10 of 1 block but xferlength == 0 */
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 1;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 0;
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 1;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 0;
|
||||
|
||||
/*
|
||||
* we don't want autoreconnect since some targets will drop the session
|
||||
* on this condition.
|
||||
*/
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
/*
|
||||
* we don't want autoreconnect since some targets will drop the session
|
||||
* on this condition.
|
||||
*/
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==0");
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==0");
|
||||
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
CU_ASSERT_NOT_EQUAL(task->status, SCSI_STATUS_CANCELLED); /* XXX redundant? */
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
CU_ASSERT_NOT_EQUAL(task->status, SCSI_STATUS_CANCELLED); /* XXX redundant? */
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
|
||||
block_size);
|
||||
if (task->residual != block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
|
||||
block_size);
|
||||
if (task->residual != block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
/* in case the previous test failed the session */
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
/* in case the previous test failed the session */
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==10000");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==10000");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 1;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 10000;
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 1;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 10000;
|
||||
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got one whole block back from the target");
|
||||
if (task->datain.size != (int)block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned %u bytes "
|
||||
"of data but should have returned %zu bytes.",
|
||||
task->datain.size,block_size);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)block_size);
|
||||
logging(LOG_VERBOSE, "Verify we got one whole block back from the target");
|
||||
if (task->datain.size != (int)block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned %u bytes "
|
||||
"of data but should have returned %zu bytes.",
|
||||
task->datain.size,block_size);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)block_size);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify residual underflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"underflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW);
|
||||
logging(LOG_VERBOSE, "Verify residual underflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"underflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual underflow",
|
||||
10000 - block_size);
|
||||
if (task->residual != 10000 - block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
10000 - block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, 10000 - block_size);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual underflow",
|
||||
10000 - block_size);
|
||||
if (task->residual != 10000 - block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
10000 - block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, 10000 - block_size);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==200");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==200");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 1;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 200;
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 1;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 200;
|
||||
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got 200 bytes back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, 200);
|
||||
logging(LOG_VERBOSE, "Verify we got 200 bytes back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, 200);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
|
||||
block_size - 200);
|
||||
if (task->residual != block_size - 200) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size - 200, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size - 200);
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
|
||||
block_size - 200);
|
||||
if (task->residual != block_size - 200) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size - 200, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size - 200);
|
||||
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try reading two blocks but iSCSI expected "
|
||||
"transfer length==%zu (==one block)", block_size);
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
logging(LOG_VERBOSE, "Try reading two blocks but iSCSI expected "
|
||||
"transfer length==%zu (==one block)", block_size);
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 2;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = block_size;
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ10;
|
||||
task->cdb[8] = 2;
|
||||
task->cdb_size = 10;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = block_size;
|
||||
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got one whole block back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)block_size);
|
||||
logging(LOG_VERBOSE, "Verify we got one whole block back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)block_size);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got one block of residual overflow");
|
||||
if (task->residual != block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size);
|
||||
logging(LOG_VERBOSE, "Verify we got one block of residual overflow");
|
||||
if (task->residual != block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size);
|
||||
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
}
|
||||
|
||||
@@ -29,26 +29,26 @@
|
||||
void
|
||||
test_read10_simple(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ10 of 1-256 blocks at the start of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ10(sd, NULL, 0, i * block_size,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ10 of 1-256 blocks at the start of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ10(sd, NULL, 0, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ10 of 1-256 blocks at the end of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ10(sd, NULL, num_blocks - i,
|
||||
logging(LOG_VERBOSE, "Test READ10 of 1-256 blocks at the end of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ10(sd, NULL, num_blocks - i,
|
||||
i * block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,25 +27,25 @@
|
||||
void
|
||||
test_read12_0blocks(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ12 0-blocks at LBA==0");
|
||||
READ12(sd, NULL, 0, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ12 0-blocks at LBA==0");
|
||||
READ12(sd, NULL, 0, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
if (num_blocks > 0x80000000) {
|
||||
CU_PASS("[SKIPPED] LUN is too big");
|
||||
return;
|
||||
}
|
||||
if (num_blocks > 0x80000000) {
|
||||
CU_PASS("[SKIPPED] LUN is too big");
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ12 0-blocks one block past end-of-LUN");
|
||||
READ12(sd, NULL, num_blocks + 1, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, "Test READ12 0-blocks one block past end-of-LUN");
|
||||
READ12(sd, NULL, num_blocks + 1, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ12 0-blocks at LBA==2^31");
|
||||
READ12(sd, NULL, 0x80000000, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, "Test READ12 0-blocks at LBA==2^31");
|
||||
READ12(sd, NULL, 0x80000000, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ12 0-blocks at LBA==-1");
|
||||
READ12(sd, NULL, -1, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, "Test READ12 0-blocks at LBA==-1");
|
||||
READ12(sd, NULL, -1, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
|
||||
@@ -28,51 +28,51 @@
|
||||
void
|
||||
test_read12_beyond_eol(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if (num_blocks >= 0x80000000) {
|
||||
CU_PASS("LUN is too big for read-beyond-eol tests with READ12. Skipping test.\n");
|
||||
return;
|
||||
}
|
||||
if (num_blocks >= 0x80000000) {
|
||||
CU_PASS("LUN is too big for read-beyond-eol tests with READ12. Skipping test.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ12 1-256 blocks one block beyond the end");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ12(sd, NULL, num_blocks + 1 - i,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ12 1-256 blocks one block beyond the end");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ12(sd, NULL, num_blocks + 1 - i,
|
||||
i * block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ12 1-256 blocks at LBA==2^31");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ12(sd, NULL, 0x80000000,
|
||||
logging(LOG_VERBOSE, "Test READ12 1-256 blocks at LBA==2^31");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ12(sd, NULL, 0x80000000,
|
||||
i * block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ12 1-256 blocks at LBA==-1");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ12(sd, NULL, -1, i * block_size,
|
||||
logging(LOG_VERBOSE, "Test READ12 1-256 blocks at LBA==-1");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ12(sd, NULL, -1, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ12 2-256 blocks all but one block beyond the end");
|
||||
for (i = 2; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ12(sd, NULL, num_blocks - 1,
|
||||
logging(LOG_VERBOSE, "Test READ12 2-256 blocks all but one block beyond the end");
|
||||
for (i = 2; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ12(sd, NULL, num_blocks - 1,
|
||||
i * block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,79 +29,79 @@
|
||||
void
|
||||
test_read12_dpofua(void)
|
||||
{
|
||||
int dpofua, usage_data_dpofua;
|
||||
struct scsi_task *ms_task = NULL;
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_task *rso_task = NULL;
|
||||
struct scsi_report_supported_op_codes_one_command *rsoc;
|
||||
int dpofua, usage_data_dpofua;
|
||||
struct scsi_task *ms_task = NULL;
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_task *rso_task = NULL;
|
||||
struct scsi_report_supported_op_codes_one_command *rsoc;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ12 DPO/FUA flags");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ12 DPO/FUA flags");
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
logging(LOG_VERBOSE, "Read the DPOFUA flag from mode sense data");
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
logging(LOG_VERBOSE, "Read the DPOFUA flag from mode sense data");
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode sense returned status GOOD");
|
||||
ms = scsi_datain_unmarshall(ms_task);
|
||||
dpofua = ms && (ms->device_specific_parameter & 0x10);
|
||||
scsi_free_scsi_task(ms_task);
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode sense returned status GOOD");
|
||||
ms = scsi_datain_unmarshall(ms_task);
|
||||
dpofua = ms && (ms->device_specific_parameter & 0x10);
|
||||
scsi_free_scsi_task(ms_task);
|
||||
|
||||
if (dpofua) {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is set. Device should allow "
|
||||
"DPO/FUA flags in CDBs");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is clear. Device should fail "
|
||||
"CDBs with DPO/FUA set");
|
||||
}
|
||||
if (dpofua) {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is set. Device should allow "
|
||||
"DPO/FUA flags in CDBs");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is clear. Device should fail "
|
||||
"CDBs with DPO/FUA set");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ12 with DPO==1");
|
||||
if (dpofua) {
|
||||
READ12(sd, NULL, 0,
|
||||
logging(LOG_VERBOSE, "Test READ12 with DPO==1");
|
||||
if (dpofua) {
|
||||
READ12(sd, NULL, 0,
|
||||
block_size, block_size, 0, 1, 0, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
} else {
|
||||
READ12(sd, NULL, 0,
|
||||
} else {
|
||||
READ12(sd, NULL, 0,
|
||||
block_size, block_size, 0, 1, 0, 0, 0, NULL,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ12 with FUA==1");
|
||||
if (dpofua) {
|
||||
READ12(sd, NULL, 0,
|
||||
logging(LOG_VERBOSE, "Test READ12 with FUA==1");
|
||||
if (dpofua) {
|
||||
READ12(sd, NULL, 0,
|
||||
block_size, block_size, 0, 0, 1, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
} else {
|
||||
READ12(sd, NULL, 0,
|
||||
} else {
|
||||
READ12(sd, NULL, 0,
|
||||
block_size, block_size, 0, 0, 1, 0, 0, NULL,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ12 with DPO==1 FUA==1");
|
||||
if (dpofua) {
|
||||
READ12(sd, NULL, 0,
|
||||
logging(LOG_VERBOSE, "Test READ12 with DPO==1 FUA==1");
|
||||
if (dpofua) {
|
||||
READ12(sd, NULL, 0,
|
||||
block_size, block_size, 0, 1, 1, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
} else {
|
||||
READ12(sd, NULL, 0,
|
||||
} else {
|
||||
READ12(sd, NULL, 0,
|
||||
block_size, block_size, 0, 1, 1, 0, 0, NULL,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Try fetching REPORT_SUPPORTED_OPCODES "
|
||||
"for READ12");
|
||||
REPORT_SUPPORTED_OPCODES(sd, &rso_task,
|
||||
logging(LOG_VERBOSE, "Try fetching REPORT_SUPPORTED_OPCODES "
|
||||
"for READ12");
|
||||
REPORT_SUPPORTED_OPCODES(sd, &rso_task,
|
||||
0, SCSI_REPORT_SUPPORTING_OPCODE,
|
||||
SCSI_OPCODE_READ12,
|
||||
0,
|
||||
65535,
|
||||
EXPECT_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc);
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc);
|
||||
|
||||
usage_data_dpofua = rsoc->cdb_usage_data[1] & 0x18;
|
||||
if (dpofua) {
|
||||
@@ -122,5 +122,5 @@ test_read12_dpofua(void)
|
||||
}
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(rso_task);
|
||||
scsi_free_scsi_task(rso_task);
|
||||
}
|
||||
|
||||
@@ -29,25 +29,25 @@
|
||||
void
|
||||
test_read12_rdprotect(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Try out different non-zero values for RDPROTECT.
|
||||
*/
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ12 with non-zero RDPROTECT");
|
||||
/*
|
||||
* Try out different non-zero values for RDPROTECT.
|
||||
*/
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ12 with non-zero RDPROTECT");
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
if (!inq->protect || (rc16 != NULL && !rc16->prot_en)) {
|
||||
logging(LOG_VERBOSE, "Device does not support/use protection information. All commands should fail.");
|
||||
for (i = 1; i < 8; i++) {
|
||||
READ12(sd, NULL, 0, block_size, block_size,
|
||||
if (!inq->protect || (rc16 != NULL && !rc16->prot_en)) {
|
||||
logging(LOG_VERBOSE, "Device does not support/use protection information. All commands should fail.");
|
||||
for (i = 1; i < 8; i++) {
|
||||
READ12(sd, NULL, 0, block_size, block_size,
|
||||
i, 0, 0, 0, 0, NULL,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_NORMAL, "No tests for devices that support protection information yet.");
|
||||
logging(LOG_NORMAL, "No tests for devices that support protection information yet.");
|
||||
}
|
||||
|
||||
@@ -31,212 +31,212 @@
|
||||
void
|
||||
test_read12_residuals(void)
|
||||
{
|
||||
struct scsi_task *task_ret;
|
||||
struct scsi_task *task_ret;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ12 commands with residuals");
|
||||
logging(LOG_VERBOSE, "Block size is %zu", block_size);
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ12 commands with residuals");
|
||||
logging(LOG_VERBOSE, "Block size is %zu", block_size);
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This READ12 test is only "
|
||||
"supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This READ12 test is only "
|
||||
"supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ12;
|
||||
task->cdb[9] = 1;
|
||||
task->cdb_size = 12;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 0;
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ12;
|
||||
task->cdb[9] = 1;
|
||||
task->cdb_size = 12;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 0;
|
||||
|
||||
/*
|
||||
* we don't want autoreconnect since some targets will drop the session
|
||||
* on this condition.
|
||||
*/
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
/*
|
||||
* we don't want autoreconnect since some targets will drop the session
|
||||
* on this condition.
|
||||
*/
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==0");
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==0");
|
||||
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
CU_ASSERT_NOT_EQUAL(task->status, SCSI_STATUS_CANCELLED); /* XXX redundant? */
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
CU_ASSERT_NOT_EQUAL(task->status, SCSI_STATUS_CANCELLED); /* XXX redundant? */
|
||||
|
||||
if (task->status == SCSI_STATUS_CHECK_CONDITION
|
||||
&& task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST
|
||||
&& task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] READ12 is not implemented on this target.");
|
||||
CU_PASS("READ12 is not implemented.");
|
||||
return;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
if (task->status == SCSI_STATUS_CHECK_CONDITION
|
||||
&& task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST
|
||||
&& task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] READ12 is not implemented on this target.");
|
||||
CU_PASS("READ12 is not implemented.");
|
||||
return;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
|
||||
block_size);
|
||||
if (task->residual != block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
|
||||
block_size);
|
||||
if (task->residual != block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
/* in case the previous test failed the session */
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
/* in case the previous test failed the session */
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==10000");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==10000");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ12;
|
||||
task->cdb[9] = 1;
|
||||
task->cdb_size = 12;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 10000;
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ12;
|
||||
task->cdb[9] = 1;
|
||||
task->cdb_size = 12;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 10000;
|
||||
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got one whole block back from the target");
|
||||
if (task->datain.size != (int)block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned %u bytes "
|
||||
"of data but should have returned %zu bytes.",
|
||||
task->datain.size,block_size);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)block_size);
|
||||
logging(LOG_VERBOSE, "Verify we got one whole block back from the target");
|
||||
if (task->datain.size != (int)block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned %u bytes "
|
||||
"of data but should have returned %zu bytes.",
|
||||
task->datain.size,block_size);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)block_size);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify residual underflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"underflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW);
|
||||
logging(LOG_VERBOSE, "Verify residual underflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"underflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual underflow",
|
||||
10000 - block_size);
|
||||
if (task->residual != 10000 - block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
10000 - block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, 10000 - block_size);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual underflow",
|
||||
10000 - block_size);
|
||||
if (task->residual != 10000 - block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
10000 - block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, 10000 - block_size);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==200");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==200");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ12;
|
||||
task->cdb[9] = 1;
|
||||
task->cdb_size = 12;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 200;
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ12;
|
||||
task->cdb[9] = 1;
|
||||
task->cdb_size = 12;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 200;
|
||||
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got 200 bytes back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, 200);
|
||||
logging(LOG_VERBOSE, "Verify we got 200 bytes back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, 200);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
|
||||
block_size - 200);
|
||||
if (task->residual != block_size - 200) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size - 200, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size - 200);
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
|
||||
block_size - 200);
|
||||
if (task->residual != block_size - 200) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size - 200, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size - 200);
|
||||
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try reading two blocks but iSCSI expected "
|
||||
"transfer length==%zu (==one block)", block_size);
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
logging(LOG_VERBOSE, "Try reading two blocks but iSCSI expected "
|
||||
"transfer length==%zu (==one block)", block_size);
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ12;
|
||||
task->cdb[9] = 2;
|
||||
task->cdb_size = 12;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = block_size;
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ12;
|
||||
task->cdb[9] = 2;
|
||||
task->cdb_size = 12;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = block_size;
|
||||
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got one whole block back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)block_size);
|
||||
logging(LOG_VERBOSE, "Verify we got one whole block back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)block_size);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got one block of residual overflow");
|
||||
if (task->residual != block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size);
|
||||
logging(LOG_VERBOSE, "Verify we got one block of residual overflow");
|
||||
if (task->residual != block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size);
|
||||
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
}
|
||||
|
||||
@@ -29,27 +29,27 @@
|
||||
void
|
||||
test_read12_simple(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ12 of 1-256 blocks at the start of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ12(sd, NULL, 0, i * block_size,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ12 of 1-256 blocks at the start of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ12(sd, NULL, 0, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ12 of 1-256 blocks at the end of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ12(sd, NULL, num_blocks - i,
|
||||
logging(LOG_VERBOSE, "Test READ12 of 1-256 blocks at the end of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ12(sd, NULL, num_blocks - i,
|
||||
i * block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,23 +27,23 @@
|
||||
void
|
||||
test_read16_0blocks(void)
|
||||
{
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ16 0-blocks at LBA==0");
|
||||
READ16(sd, NULL, 0, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ16 0-blocks at LBA==0");
|
||||
READ16(sd, NULL, 0, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ16 0-blocks one block past end-of-LUN");
|
||||
READ16(sd, NULL, num_blocks + 1, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, "Test READ16 0-blocks one block past end-of-LUN");
|
||||
READ16(sd, NULL, num_blocks + 1, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ16 0-blocks at LBA==2^63");
|
||||
READ16(sd, NULL, 0x8000000000000000ULL, 0,
|
||||
logging(LOG_VERBOSE, "Test READ16 0-blocks at LBA==2^63");
|
||||
READ16(sd, NULL, 0x8000000000000000ULL, 0,
|
||||
block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ16 0-blocks at LBA==-1");
|
||||
READ16(sd, NULL, -1, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, "Test READ16 0-blocks at LBA==-1");
|
||||
READ16(sd, NULL, -1, 0, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
|
||||
@@ -27,82 +27,82 @@
|
||||
|
||||
static int ilog2(size_t i)
|
||||
{
|
||||
int j = -1;
|
||||
int j = -1;
|
||||
|
||||
while (i) {
|
||||
i >>= 1;
|
||||
j++;
|
||||
}
|
||||
return j;
|
||||
while (i) {
|
||||
i >>= 1;
|
||||
j++;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
void
|
||||
test_read16_beyond_eol(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ16 1-256 blocks one block beyond the end");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ16(sd, NULL, num_blocks + 1 - i,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ16 1-256 blocks one block beyond the end");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ16(sd, NULL, num_blocks + 1 - i,
|
||||
i * block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ16 1-256 blocks at LBA==2^63");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ16(sd, NULL, 0x8000000000000000ULL,
|
||||
logging(LOG_VERBOSE, "Test READ16 1-256 blocks at LBA==2^63");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ16(sd, NULL, 0x8000000000000000ULL,
|
||||
i * block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ16 1-256 blocks at LBA==2^%d",
|
||||
64 - ilog2(block_size));
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ16(sd, NULL, 1ULL << (64 - ilog2(block_size)),
|
||||
logging(LOG_VERBOSE, "Test READ16 1-256 blocks at LBA==2^%d",
|
||||
64 - ilog2(block_size));
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ16(sd, NULL, 1ULL << (64 - ilog2(block_size)),
|
||||
i * block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ16 1-256 blocks at LBA==2^%d",
|
||||
63 - ilog2(block_size));
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ16(sd, NULL, 1ULL << (63 - ilog2(block_size)),
|
||||
logging(LOG_VERBOSE, "Test READ16 1-256 blocks at LBA==2^%d",
|
||||
63 - ilog2(block_size));
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ16(sd, NULL, 1ULL << (63 - ilog2(block_size)),
|
||||
i * block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ16 1-256 blocks at LBA==-1");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ16(sd, NULL, -1, i * block_size,
|
||||
logging(LOG_VERBOSE, "Test READ16 1-256 blocks at LBA==-1");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ16(sd, NULL, -1, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ16 2-256 blocks all but one block beyond the end");
|
||||
for (i = 2; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ16(sd, NULL, num_blocks - 1,
|
||||
logging(LOG_VERBOSE, "Test READ16 2-256 blocks all but one block beyond the end");
|
||||
for (i = 2; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ16(sd, NULL, num_blocks - 1,
|
||||
i * block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,73 +29,73 @@
|
||||
void
|
||||
test_read16_dpofua(void)
|
||||
{
|
||||
int dpofua, usage_data_dpofua;
|
||||
struct scsi_task *ms_task = NULL;
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_task *rso_task = NULL;
|
||||
struct scsi_report_supported_op_codes_one_command *rsoc;
|
||||
int dpofua, usage_data_dpofua;
|
||||
struct scsi_task *ms_task = NULL;
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_task *rso_task = NULL;
|
||||
struct scsi_report_supported_op_codes_one_command *rsoc;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ16 DPO/FUA flags");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ16 DPO/FUA flags");
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
logging(LOG_VERBOSE, "Read the DPOFUA flag from mode sense data");
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
logging(LOG_VERBOSE, "Read the DPOFUA flag from mode sense data");
|
||||
MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode sense returned status GOOD");
|
||||
ms = scsi_datain_unmarshall(ms_task);
|
||||
dpofua = ms && (ms->device_specific_parameter & 0x10);
|
||||
scsi_free_scsi_task(ms_task);
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode sense returned status GOOD");
|
||||
ms = scsi_datain_unmarshall(ms_task);
|
||||
dpofua = ms && (ms->device_specific_parameter & 0x10);
|
||||
scsi_free_scsi_task(ms_task);
|
||||
|
||||
if (dpofua) {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is set. Device should allow "
|
||||
"DPO/FUA flags in CDBs");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is clear. Device should fail "
|
||||
"CDBs with DPO/FUA set");
|
||||
}
|
||||
if (dpofua) {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is set. Device should allow "
|
||||
"DPO/FUA flags in CDBs");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "DPOFUA flag is clear. Device should fail "
|
||||
"CDBs with DPO/FUA set");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ16 with DPO==1");
|
||||
if (dpofua) {
|
||||
READ16(sd, NULL, 0, block_size, block_size, 0, 1, 0, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, "Test READ16 with DPO==1");
|
||||
if (dpofua) {
|
||||
READ16(sd, NULL, 0, block_size, block_size, 0, 1, 0, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
} else {
|
||||
READ16(sd, NULL, 0, block_size, block_size, 0, 1, 0, 0, 0, NULL,
|
||||
} else {
|
||||
READ16(sd, NULL, 0, block_size, block_size, 0, 1, 0, 0, 0, NULL,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ16 with FUA==1");
|
||||
if (dpofua) {
|
||||
READ16(sd, NULL, 0, block_size, block_size, 0, 0, 1, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, "Test READ16 with FUA==1");
|
||||
if (dpofua) {
|
||||
READ16(sd, NULL, 0, block_size, block_size, 0, 0, 1, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
} else {
|
||||
READ16(sd, NULL, 0, block_size, block_size, 0, 0, 1, 0, 0, NULL,
|
||||
} else {
|
||||
READ16(sd, NULL, 0, block_size, block_size, 0, 0, 1, 0, 0, NULL,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ16 with DPO==1 FUA==1");
|
||||
if (dpofua) {
|
||||
READ16(sd, NULL, 0, block_size, block_size, 0, 1, 1, 0, 0, NULL,
|
||||
logging(LOG_VERBOSE, "Test READ16 with DPO==1 FUA==1");
|
||||
if (dpofua) {
|
||||
READ16(sd, NULL, 0, block_size, block_size, 0, 1, 1, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
} else {
|
||||
READ16(sd, NULL, 0, block_size, block_size, 0, 1, 1, 0, 0, NULL,
|
||||
} else {
|
||||
READ16(sd, NULL, 0, block_size, block_size, 0, 1, 1, 0, 0, NULL,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Try fetching REPORT_SUPPORTED_OPCODES "
|
||||
"for READ16");
|
||||
REPORT_SUPPORTED_OPCODES(sd, &rso_task,
|
||||
logging(LOG_VERBOSE, "Try fetching REPORT_SUPPORTED_OPCODES "
|
||||
"for READ16");
|
||||
REPORT_SUPPORTED_OPCODES(sd, &rso_task,
|
||||
0, SCSI_REPORT_SUPPORTING_OPCODE,
|
||||
SCSI_OPCODE_READ16,
|
||||
0,
|
||||
65535,
|
||||
EXPECT_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc);
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc);
|
||||
|
||||
usage_data_dpofua = rsoc->cdb_usage_data[1] & 0x18;
|
||||
if (dpofua) {
|
||||
@@ -116,5 +116,5 @@ test_read16_dpofua(void)
|
||||
}
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(rso_task);
|
||||
scsi_free_scsi_task(rso_task);
|
||||
}
|
||||
|
||||
@@ -29,24 +29,24 @@
|
||||
void
|
||||
test_read16_rdprotect(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Try out different non-zero values for RDPROTECT.
|
||||
*/
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ16 with non-zero RDPROTECT");
|
||||
/*
|
||||
* Try out different non-zero values for RDPROTECT.
|
||||
*/
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ16 with non-zero RDPROTECT");
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
if (!inq->protect || (rc16 != NULL && !rc16->prot_en)) {
|
||||
logging(LOG_VERBOSE, "Device does not support/use protection information. All commands should fail.");
|
||||
for (i = 1; i < 8; i++) {
|
||||
READ16(sd, NULL, 0, block_size, block_size,
|
||||
if (!inq->protect || (rc16 != NULL && !rc16->prot_en)) {
|
||||
logging(LOG_VERBOSE, "Device does not support/use protection information. All commands should fail.");
|
||||
for (i = 1; i < 8; i++) {
|
||||
READ16(sd, NULL, 0, block_size, block_size,
|
||||
i, 0, 0, 0, 0, NULL,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
return;
|
||||
}
|
||||
logging(LOG_NORMAL, "No tests for devices that support protection information yet.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
logging(LOG_NORMAL, "No tests for devices that support protection information yet.");
|
||||
}
|
||||
|
||||
@@ -31,212 +31,212 @@
|
||||
void
|
||||
test_read16_residuals(void)
|
||||
{
|
||||
struct scsi_task *task_ret;
|
||||
struct scsi_task *task_ret;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ16 commands with residuals");
|
||||
logging(LOG_VERBOSE, "Block size is %zu", block_size);
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ16 commands with residuals");
|
||||
logging(LOG_VERBOSE, "Block size is %zu", block_size);
|
||||
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This READ16 test is only "
|
||||
"supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
if (sd->iscsi_ctx == NULL) {
|
||||
const char *err = "[SKIPPED] This READ16 test is only "
|
||||
"supported for iSCSI backends";
|
||||
logging(LOG_NORMAL, "%s", err);
|
||||
CU_PASS(err);
|
||||
return;
|
||||
}
|
||||
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ16;
|
||||
task->cdb[13] = 1;
|
||||
task->cdb_size = 16;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 0;
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ16;
|
||||
task->cdb[13] = 1;
|
||||
task->cdb_size = 16;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 0;
|
||||
|
||||
/*
|
||||
* we don't want autoreconnect since some targets will drop the session
|
||||
* on this condition.
|
||||
*/
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
/*
|
||||
* we don't want autoreconnect since some targets will drop the session
|
||||
* on this condition.
|
||||
*/
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==0");
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==0");
|
||||
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
CU_ASSERT_NOT_EQUAL(task->status, SCSI_STATUS_CANCELLED); /* XXX redundant? */
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
CU_ASSERT_NOT_EQUAL(task->status, SCSI_STATUS_CANCELLED); /* XXX redundant? */
|
||||
|
||||
if (task->status == SCSI_STATUS_CHECK_CONDITION
|
||||
&& task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST
|
||||
&& task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] READ16 is not implemented on this target and it does not claim SBC-3 support.");
|
||||
CU_PASS("READ16 is not implemented and no SBC-3 support claimed.");
|
||||
return;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
if (task->status == SCSI_STATUS_CHECK_CONDITION
|
||||
&& task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST
|
||||
&& task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] READ16 is not implemented on this target and it does not claim SBC-3 support.");
|
||||
CU_PASS("READ16 is not implemented and no SBC-3 support claimed.");
|
||||
return;
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
|
||||
block_size);
|
||||
if (task->residual != block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
|
||||
block_size);
|
||||
if (task->residual != block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
/* in case the previous test failed the session */
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
/* in case the previous test failed the session */
|
||||
iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==10000");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==10000");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ16;
|
||||
task->cdb[13] = 1;
|
||||
task->cdb_size = 16;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 10000;
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ16;
|
||||
task->cdb[13] = 1;
|
||||
task->cdb_size = 16;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 10000;
|
||||
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got one whole block back from the target");
|
||||
if (task->datain.size != (int)block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned %u bytes "
|
||||
"of data but should have returned %zu bytes.",
|
||||
task->datain.size,block_size);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)block_size);
|
||||
logging(LOG_VERBOSE, "Verify we got one whole block back from the target");
|
||||
if (task->datain.size != (int)block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned %u bytes "
|
||||
"of data but should have returned %zu bytes.",
|
||||
task->datain.size,block_size);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)block_size);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify residual underflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"underflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW);
|
||||
logging(LOG_VERBOSE, "Verify residual underflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"underflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual underflow",
|
||||
10000 - block_size);
|
||||
if (task->residual != 10000 - block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
10000 - block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, 10000 - block_size);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual underflow",
|
||||
10000 - block_size);
|
||||
if (task->residual != 10000 - block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
10000 - block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, 10000 - block_size);
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==200");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
logging(LOG_VERBOSE, "Try reading one block but with iSCSI expected transfer length==200");
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ16;
|
||||
task->cdb[13] = 1;
|
||||
task->cdb_size = 16;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 200;
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ16;
|
||||
task->cdb[13] = 1;
|
||||
task->cdb_size = 16;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = 200;
|
||||
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got 200 bytes back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, 200);
|
||||
logging(LOG_VERBOSE, "Verify we got 200 bytes back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, 200);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
|
||||
block_size - 200);
|
||||
if (task->residual != block_size - 200) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size - 200, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size - 200);
|
||||
logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
|
||||
block_size - 200);
|
||||
if (task->residual != block_size - 200) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size - 200, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size - 200);
|
||||
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try reading two blocks but iSCSI expected "
|
||||
"transfer length==%zu (==one block)", block_size);
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
logging(LOG_VERBOSE, "Try reading two blocks but iSCSI expected "
|
||||
"transfer length==%zu (==one block)", block_size);
|
||||
task = malloc(sizeof(struct scsi_task));
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ16;
|
||||
task->cdb[13] = 2;
|
||||
task->cdb_size = 16;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = block_size;
|
||||
memset(task, 0, sizeof(struct scsi_task));
|
||||
task->cdb[0] = SCSI_OPCODE_READ16;
|
||||
task->cdb[13] = 2;
|
||||
task->cdb_size = 16;
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
task->expxferlen = block_size;
|
||||
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
|
||||
iscsi_get_error(sd->iscsi_ctx));
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got one whole block back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)block_size);
|
||||
logging(LOG_VERBOSE, "Verify we got one whole block back from the target");
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)block_size);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
logging(LOG_VERBOSE, "Verify residual overflow flag is set");
|
||||
if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
|
||||
"overflow flag");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify we got one block of residual overflow");
|
||||
if (task->residual != block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size);
|
||||
logging(LOG_VERBOSE, "Verify we got one block of residual overflow");
|
||||
if (task->residual != block_size) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
|
||||
"amount of residual. Expected %zu but got %zu.",
|
||||
block_size, task->residual);
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->residual, block_size);
|
||||
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
}
|
||||
|
||||
@@ -29,29 +29,29 @@
|
||||
void
|
||||
test_read16_simple(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ16 of 1-256 blocks at the start of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ16(sd, NULL, 0, i * block_size,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ16 of 1-256 blocks at the start of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ16(sd, NULL, 0, i * block_size,
|
||||
block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ16 of 1-256 blocks at the end of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ16(sd, NULL, num_blocks - i,
|
||||
logging(LOG_VERBOSE, "Test READ16 of 1-256 blocks at the end of the LUN");
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ16(sd, NULL, num_blocks - i,
|
||||
i * block_size, block_size, 0, 0, 0, 0, 0, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,36 +28,36 @@
|
||||
void
|
||||
test_read6_beyond_eol(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if (num_blocks > 0x1fffff) {
|
||||
CU_PASS("LUN is too big for read-beyond-eol tests with READ6. Skipping test.\n");
|
||||
return;
|
||||
}
|
||||
if (num_blocks > 0x1fffff) {
|
||||
CU_PASS("LUN is too big for read-beyond-eol tests with READ6. Skipping test.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ6 1-255 blocks one block beyond the end");
|
||||
for (i = 1; i <= 255 && i + 0U <= num_blocks + 1; i++) {
|
||||
READ6(sd, NULL, num_blocks + 1 - i,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ6 1-255 blocks one block beyond the end");
|
||||
for (i = 1; i <= 255 && i + 0U <= num_blocks + 1; i++) {
|
||||
READ6(sd, NULL, num_blocks + 1 - i,
|
||||
i * block_size, block_size, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ6 1-255 blocks at LBA==0x1fffff");
|
||||
for (i = 1; i <= 255; i++) {
|
||||
READ6(sd, NULL, 0x1fffff, i * block_size, block_size, NULL,
|
||||
logging(LOG_VERBOSE, "Test READ6 1-255 blocks at LBA==0x1fffff");
|
||||
for (i = 1; i <= 255; i++) {
|
||||
READ6(sd, NULL, 0x1fffff, i * block_size, block_size, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
|
||||
if (num_blocks == 0) {
|
||||
CU_PASS("LUN is too small for read-beyond-eol tests with READ6. Skipping test.\n");
|
||||
return;
|
||||
}
|
||||
if (num_blocks == 0) {
|
||||
CU_PASS("LUN is too small for read-beyond-eol tests with READ6. Skipping test.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ6 2-255 blocks all but one block beyond the end");
|
||||
for (i = 2; i <= 255; i++) {
|
||||
READ6(sd, NULL, num_blocks - 1,
|
||||
logging(LOG_VERBOSE, "Test READ6 2-255 blocks all but one block beyond the end");
|
||||
for (i = 2; i <= 255; i++) {
|
||||
READ6(sd, NULL, num_blocks - 1,
|
||||
i * block_size, block_size, NULL,
|
||||
EXPECT_LBA_OOB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,54 +29,54 @@
|
||||
void
|
||||
test_read6_simple(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ6 of 1-255 blocks at the start of the LUN");
|
||||
for (i = 1; i <= 255; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ6(sd, NULL, 0, i * block_size, block_size, NULL,
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ6 of 1-255 blocks at the start of the LUN");
|
||||
for (i = 1; i <= 255; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ6(sd, NULL, 0, i * block_size, block_size, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ6 of 1-255 blocks at the end of the LUN");
|
||||
if (num_blocks > 0x200000) {
|
||||
CU_PASS("LUN is too big for read-at-eol tests with READ6. Skipping test.\n");
|
||||
} else {
|
||||
for (i = 1; i <= 255 && i + 0U <= num_blocks; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ6(sd, NULL, num_blocks - i,
|
||||
logging(LOG_VERBOSE, "Test READ6 of 1-255 blocks at the end of the LUN");
|
||||
if (num_blocks > 0x200000) {
|
||||
CU_PASS("LUN is too big for read-at-eol tests with READ6. Skipping test.\n");
|
||||
} else {
|
||||
for (i = 1; i <= 255 && i + 0U <= num_blocks; i++) {
|
||||
if (maximum_transfer_length && maximum_transfer_length < i) {
|
||||
break;
|
||||
}
|
||||
READ6(sd, NULL, num_blocks - i,
|
||||
i * block_size, block_size, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 256 is converted to 0 when the CDB is marshalled by the helper */
|
||||
if (maximum_transfer_length >= 256) {
|
||||
logging(LOG_VERBOSE, "Transfer length == 0 means we want to "
|
||||
"transfer 256 blocks");
|
||||
READ6(sd, &task, 0,
|
||||
/* 256 is converted to 0 when the CDB is marshalled by the helper */
|
||||
if (maximum_transfer_length >= 256) {
|
||||
logging(LOG_VERBOSE, "Transfer length == 0 means we want to "
|
||||
"transfer 256 blocks");
|
||||
READ6(sd, &task, 0,
|
||||
256 * block_size, block_size, NULL,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_NORMAL, "[FAILED] READ6 command: "
|
||||
"failed with sense. %s", sd->error_str );
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_NORMAL, "[FAILED] READ6 command: "
|
||||
"failed with sense. %s", sd->error_str );
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that we did get 256 blocks of "
|
||||
"data back");
|
||||
if (task->datain.size == (int)(256 * block_size)) {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Target returned 256 "
|
||||
"blocks of data");
|
||||
} else {
|
||||
logging(LOG_NORMAL, "[FAILED] Target did not return "
|
||||
"256 blocks of data");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)(256 * block_size));
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify that we did get 256 blocks of "
|
||||
"data back");
|
||||
if (task->datain.size == (int)(256 * block_size)) {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Target returned 256 "
|
||||
"blocks of data");
|
||||
} else {
|
||||
logging(LOG_NORMAL, "[FAILED] Target did not return "
|
||||
"256 blocks of data");
|
||||
}
|
||||
CU_ASSERT_EQUAL(task->datain.size, (int)(256 * block_size));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
void
|
||||
test_readcapacity10_simple(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test basic READCAPACITY10");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test basic READCAPACITY10");
|
||||
|
||||
READCAPACITY10(sd, NULL, 0, 0,
|
||||
READCAPACITY10(sd, NULL, 0, 0,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
|
||||
@@ -29,13 +29,13 @@
|
||||
void
|
||||
test_readcapacity16_alloclen(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that READCAPACITY16 with alloc_len 0-15 is not an error");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that READCAPACITY16 with alloc_len 0-15 is not an error");
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
READCAPACITY16(sd, NULL, i,
|
||||
for (i = 0; i < 16; i++) {
|
||||
READCAPACITY16(sd, NULL, i,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,95 +29,95 @@
|
||||
void
|
||||
test_readcapacity16_protection(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READCAPACITY16 Protection Information");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READCAPACITY16 Protection Information");
|
||||
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
if (rc16 == NULL) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] READCAPACITY16 is not implemented on this target.");
|
||||
CU_PASS("READCAPACITY16 is not implemented.");
|
||||
return;
|
||||
}
|
||||
if (rc16 == NULL) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] READCAPACITY16 is not implemented on this target.");
|
||||
CU_PASS("READCAPACITY16 is not implemented.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!inq->protect) {
|
||||
logging(LOG_VERBOSE, "This device does not support PI. "
|
||||
"Verify that all relevant fields in READCAPACITY16 "
|
||||
"are 0");
|
||||
if (!inq->protect) {
|
||||
logging(LOG_VERBOSE, "This device does not support PI. "
|
||||
"Verify that all relevant fields in READCAPACITY16 "
|
||||
"are 0");
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that PROT_EN is 0");
|
||||
if (rc16->prot_en) {
|
||||
logging(LOG_VERBOSE, "[FAILED] PROT_EN is set but "
|
||||
"the device does not claim support for "
|
||||
"protection information in the standard "
|
||||
"inquiry VPD.");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] PROT_EN is 0");
|
||||
}
|
||||
CU_ASSERT_EQUAL(rc16->prot_en, 0);
|
||||
logging(LOG_VERBOSE, "Verify that PROT_EN is 0");
|
||||
if (rc16->prot_en) {
|
||||
logging(LOG_VERBOSE, "[FAILED] PROT_EN is set but "
|
||||
"the device does not claim support for "
|
||||
"protection information in the standard "
|
||||
"inquiry VPD.");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] PROT_EN is 0");
|
||||
}
|
||||
CU_ASSERT_EQUAL(rc16->prot_en, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that P_TYPE is 0");
|
||||
if (rc16->p_type) {
|
||||
logging(LOG_VERBOSE, "[FAILED] P_TYPE is non-zero but "
|
||||
"the device does not claim support for "
|
||||
"protection information in the standard "
|
||||
"inquiry VPD.");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] P_TYPE is 0");
|
||||
}
|
||||
CU_ASSERT_EQUAL(rc16->p_type, 0);
|
||||
logging(LOG_VERBOSE, "Verify that P_TYPE is 0");
|
||||
if (rc16->p_type) {
|
||||
logging(LOG_VERBOSE, "[FAILED] P_TYPE is non-zero but "
|
||||
"the device does not claim support for "
|
||||
"protection information in the standard "
|
||||
"inquiry VPD.");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] P_TYPE is 0");
|
||||
}
|
||||
CU_ASSERT_EQUAL(rc16->p_type, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that P_I_EXP is 0");
|
||||
if (rc16->p_i_exp) {
|
||||
logging(LOG_VERBOSE, "[FAILED] P_I_EXP is non-zero but "
|
||||
"the device does not claim support for "
|
||||
"protection information in the standard "
|
||||
"inquiry VPD.");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] P_I_EXP is 0");
|
||||
}
|
||||
CU_ASSERT_EQUAL(rc16->p_i_exp, 0);
|
||||
logging(LOG_VERBOSE, "Verify that P_I_EXP is 0");
|
||||
if (rc16->p_i_exp) {
|
||||
logging(LOG_VERBOSE, "[FAILED] P_I_EXP is non-zero but "
|
||||
"the device does not claim support for "
|
||||
"protection information in the standard "
|
||||
"inquiry VPD.");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] P_I_EXP is 0");
|
||||
}
|
||||
CU_ASSERT_EQUAL(rc16->p_i_exp, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "This device supports PI. "
|
||||
"Verify that all relevant fields are sane");
|
||||
if (!rc16->prot_en) {
|
||||
logging(LOG_VERBOSE, "Protection is not enabled. Verify "
|
||||
"that all relevant fields are zero");
|
||||
logging(LOG_VERBOSE, "This device supports PI. "
|
||||
"Verify that all relevant fields are sane");
|
||||
if (!rc16->prot_en) {
|
||||
logging(LOG_VERBOSE, "Protection is not enabled. Verify "
|
||||
"that all relevant fields are zero");
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that P_TYPE is 0");
|
||||
if (rc16->p_type) {
|
||||
logging(LOG_VERBOSE, "[FAILED] P_TYPE is non-zero but "
|
||||
"protection information is not enabled.");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] P_TYPE is 0");
|
||||
}
|
||||
CU_ASSERT_EQUAL(rc16->p_type, 0);
|
||||
logging(LOG_VERBOSE, "Verify that P_TYPE is 0");
|
||||
if (rc16->p_type) {
|
||||
logging(LOG_VERBOSE, "[FAILED] P_TYPE is non-zero but "
|
||||
"protection information is not enabled.");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] P_TYPE is 0");
|
||||
}
|
||||
CU_ASSERT_EQUAL(rc16->p_type, 0);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that P_I_EXP is 0");
|
||||
if (rc16->p_i_exp) {
|
||||
logging(LOG_VERBOSE, "[FAILED] P_I_EXP is non-zero but "
|
||||
"protection information is not enabled");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] P_I_EXP is 0");
|
||||
}
|
||||
CU_ASSERT_EQUAL(rc16->p_i_exp, 0);
|
||||
logging(LOG_VERBOSE, "Verify that P_I_EXP is 0");
|
||||
if (rc16->p_i_exp) {
|
||||
logging(LOG_VERBOSE, "[FAILED] P_I_EXP is non-zero but "
|
||||
"protection information is not enabled");
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] P_I_EXP is 0");
|
||||
}
|
||||
CU_ASSERT_EQUAL(rc16->p_i_exp, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Protection is enabled. Verify "
|
||||
"that all relevant fields are sane");
|
||||
switch (rc16->p_type) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
break;
|
||||
default:
|
||||
logging(LOG_VERBOSE, "[FAILED] P_TYPE is invalid. Must be "
|
||||
"0,1,2 but was %d", rc16->p_type);
|
||||
CU_FAIL("P_TYPE is invalid");
|
||||
}
|
||||
logging(LOG_VERBOSE, "Protection is enabled. Verify "
|
||||
"that all relevant fields are sane");
|
||||
switch (rc16->p_type) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
break;
|
||||
default:
|
||||
logging(LOG_VERBOSE, "[FAILED] P_TYPE is invalid. Must be "
|
||||
"0,1,2 but was %d", rc16->p_type);
|
||||
CU_FAIL("P_TYPE is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
void
|
||||
test_readcapacity16_simple(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that READCAPACITY16 works");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that READCAPACITY16 works");
|
||||
|
||||
READCAPACITY16(sd, NULL, 16,
|
||||
READCAPACITY16(sd, NULL, 16,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
|
||||
@@ -31,19 +31,19 @@ test_readcapacity16_support(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that READCAPACITY16 is supported on SBC3");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that READCAPACITY16 is supported on SBC3");
|
||||
|
||||
ret = readcapacity16(sd, NULL, 15,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (ret == -2) {
|
||||
if (sbc3_support) {
|
||||
logging(LOG_NORMAL, "[FAILED] READCAPACITY16 is not available but the device claims SBC-3 support.");
|
||||
CU_FAIL("READCAPACITY16 failed but the device claims SBC-3 support.");
|
||||
} else {
|
||||
logging(LOG_NORMAL, "[SKIPPED] READCAPACITY16 is not implemented on this target and it does not claim SBC-3 support.");
|
||||
}
|
||||
} else {
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
ret = readcapacity16(sd, NULL, 15,
|
||||
EXPECT_STATUS_GOOD);
|
||||
if (ret == -2) {
|
||||
if (sbc3_support) {
|
||||
logging(LOG_NORMAL, "[FAILED] READCAPACITY16 is not available but the device claims SBC-3 support.");
|
||||
CU_FAIL("READCAPACITY16 failed but the device claims SBC-3 support.");
|
||||
} else {
|
||||
logging(LOG_NORMAL, "[SKIPPED] READCAPACITY16 is not implemented on this target and it does not claim SBC-3 support.");
|
||||
}
|
||||
} else {
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,38 +28,38 @@
|
||||
static void
|
||||
test_write10(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test WRITE10 fails with WRITE_PROTECTED");
|
||||
memset(scratch, 0xa6, block_size);
|
||||
WRITE10(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Test WRITE10 fails with WRITE_PROTECTED");
|
||||
memset(scratch, 0xa6, block_size);
|
||||
WRITE10(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_WRITE_PROTECTED);
|
||||
}
|
||||
|
||||
static void
|
||||
test_write12(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test WRITE12 fails with WRITE_PROTECTED");
|
||||
memset(scratch, 0xa6, block_size);
|
||||
WRITE12(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Test WRITE12 fails with WRITE_PROTECTED");
|
||||
memset(scratch, 0xa6, block_size);
|
||||
WRITE12(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_WRITE_PROTECTED);
|
||||
}
|
||||
|
||||
static void
|
||||
test_write16(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test WRITE16 fails with WRITE_PROTECTED");
|
||||
memset(scratch, 0xa6, block_size);
|
||||
WRITE16(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Test WRITE16 fails with WRITE_PROTECTED");
|
||||
memset(scratch, 0xa6, block_size);
|
||||
WRITE16(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_WRITE_PROTECTED);
|
||||
}
|
||||
|
||||
static void
|
||||
test_writesame10(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test WRITE_SAME10 fails with WRITE_PROTECTED");
|
||||
logging(LOG_VERBOSE, "Test WRITE_SAME10 fails with WRITE_PROTECTED");
|
||||
WRITESAME10(sd, 0, block_size, 1, 0, 0, 0, 0, scratch,
|
||||
EXPECT_WRITE_PROTECTED);
|
||||
|
||||
logging(LOG_VERBOSE, "Test WRITE_SAME10 UNMAP fails with "
|
||||
logging(LOG_VERBOSE, "Test WRITE_SAME10 UNMAP fails with "
|
||||
"WRITE_PROTECTED");
|
||||
WRITESAME10(sd, 0, block_size, 1, 0, 1, 0, 0, NULL,
|
||||
EXPECT_WRITE_PROTECTED);
|
||||
@@ -68,11 +68,11 @@ test_writesame10(void)
|
||||
static void
|
||||
test_writesame16(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test WRITE_SAME16 fails with WRITE_PROTECTED");
|
||||
logging(LOG_VERBOSE, "Test WRITE_SAME16 fails with WRITE_PROTECTED");
|
||||
WRITESAME16(sd, 0, block_size, 1, 0, 0, 0, 0, scratch,
|
||||
EXPECT_WRITE_PROTECTED);
|
||||
|
||||
logging(LOG_VERBOSE, "Test WRITE_SAME16 UNMAP fails with "
|
||||
logging(LOG_VERBOSE, "Test WRITE_SAME16 UNMAP fails with "
|
||||
"WRITE_PROTECTED");
|
||||
WRITESAME16(sd, 0, block_size, 1, 0, 1, 0, 0, NULL,
|
||||
EXPECT_WRITE_PROTECTED);
|
||||
@@ -81,39 +81,39 @@ test_writesame16(void)
|
||||
static void
|
||||
test_writeverify10(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test WRITEVERIFY10 fails with WRITE_PROTECTED");
|
||||
WRITEVERIFY10(sd, 0, block_size, block_size, 0, 0, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Test WRITEVERIFY10 fails with WRITE_PROTECTED");
|
||||
WRITEVERIFY10(sd, 0, block_size, block_size, 0, 0, 0, 0, scratch,
|
||||
EXPECT_WRITE_PROTECTED);
|
||||
}
|
||||
|
||||
static void
|
||||
test_writeverify12(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test WRITEVERIFY12 fails with WRITE_PROTECTED");
|
||||
WRITEVERIFY12(sd, 0, block_size, block_size, 0, 0, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Test WRITEVERIFY12 fails with WRITE_PROTECTED");
|
||||
WRITEVERIFY12(sd, 0, block_size, block_size, 0, 0, 0, 0, scratch,
|
||||
EXPECT_WRITE_PROTECTED);
|
||||
}
|
||||
|
||||
static void
|
||||
test_writeverify16(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test WRITEVERIFY16 fails with WRITE_PROTECTED");
|
||||
WRITEVERIFY16(sd, 0, block_size, block_size, 0, 0, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Test WRITEVERIFY16 fails with WRITE_PROTECTED");
|
||||
WRITEVERIFY16(sd, 0, block_size, block_size, 0, 0, 0, 0, scratch,
|
||||
EXPECT_WRITE_PROTECTED);
|
||||
}
|
||||
|
||||
static void
|
||||
test_orwrite(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test ORWRITE fails with WRITE_PROTECTED");
|
||||
ORWRITE(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
logging(LOG_VERBOSE, "Test ORWRITE fails with WRITE_PROTECTED");
|
||||
ORWRITE(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
|
||||
EXPECT_WRITE_PROTECTED);
|
||||
}
|
||||
|
||||
static void
|
||||
test_compareandwrite(void)
|
||||
{
|
||||
logging(LOG_VERBOSE, "Test COMPAREANDWRITE fails with WRITE_PROTECTED");
|
||||
logging(LOG_VERBOSE, "Test COMPAREANDWRITE fails with WRITE_PROTECTED");
|
||||
COMPAREANDWRITE(sd, 0, scratch, 2 * block_size, block_size, 0, 0, 0, 0,
|
||||
EXPECT_WRITE_PROTECTED);
|
||||
}
|
||||
@@ -121,32 +121,32 @@ test_compareandwrite(void)
|
||||
static void
|
||||
test_unmap(void)
|
||||
{
|
||||
struct unmap_list list[1];
|
||||
struct unmap_list list[1];
|
||||
|
||||
logging(LOG_VERBOSE, "Test UNMAP of one physical block fails with "
|
||||
logging(LOG_VERBOSE, "Test UNMAP of one physical block fails with "
|
||||
"WRITE_PROTECTED");
|
||||
list[0].lba = 0;
|
||||
list[0].num = lbppb;
|
||||
UNMAP(sd, 0, list, 1,
|
||||
list[0].lba = 0;
|
||||
list[0].num = lbppb;
|
||||
UNMAP(sd, 0, list, 1,
|
||||
EXPECT_WRITE_PROTECTED);
|
||||
|
||||
logging(LOG_VERBOSE, "Test UNMAP of one logical block fails with "
|
||||
logging(LOG_VERBOSE, "Test UNMAP of one logical block fails with "
|
||||
"WRITE_PROTECTED");
|
||||
list[0].lba = 0;
|
||||
list[0].num = 1;
|
||||
UNMAP(sd, 0, list, 1,
|
||||
list[0].lba = 0;
|
||||
list[0].num = 1;
|
||||
UNMAP(sd, 0, list, 1,
|
||||
EXPECT_WRITE_PROTECTED);
|
||||
}
|
||||
|
||||
void
|
||||
test_readonly_sbc(void)
|
||||
{
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_READONLY;
|
||||
CHECK_FOR_SBC;
|
||||
CHECK_FOR_DATALOSS;
|
||||
CHECK_FOR_READONLY;
|
||||
CHECK_FOR_SBC;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that Medium write commands fail for READ-ONLY SBC devices");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test that Medium write commands fail for READ-ONLY SBC devices");
|
||||
|
||||
test_compareandwrite();
|
||||
test_orwrite();
|
||||
|
||||
@@ -30,52 +30,52 @@
|
||||
void
|
||||
test_receive_copy_results_copy_status(void)
|
||||
{
|
||||
struct scsi_task *cs_task;
|
||||
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;
|
||||
struct scsi_task *cs_task;
|
||||
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, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test RECEIVE COPY RESULTS, COPY STATUS");
|
||||
|
||||
logging(LOG_VERBOSE, "No copy in progress");
|
||||
RECEIVE_COPY_RESULTS(&cs_task, sd, SCSI_COPY_RESULTS_COPY_STATUS,
|
||||
logging(LOG_VERBOSE, "No copy in progress");
|
||||
RECEIVE_COPY_RESULTS(&cs_task, sd, SCSI_COPY_RESULTS_COPY_STATUS,
|
||||
list_id, NULL, EXPECT_INVALID_FIELD_IN_CDB);
|
||||
scsi_free_scsi_task(cs_task);
|
||||
cs_task = NULL;
|
||||
scsi_free_scsi_task(cs_task);
|
||||
cs_task = NULL;
|
||||
|
||||
CHECK_FOR_DATALOSS;
|
||||
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;
|
||||
memset(xcopybuf, 0, data.size);
|
||||
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;
|
||||
memset(xcopybuf, 0, data.size);
|
||||
|
||||
/* 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;
|
||||
/* 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;
|
||||
|
||||
/* Initialize 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 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);
|
||||
/* Initialize the parameter list header */
|
||||
populate_param_header(xcopybuf, list_id, 0, 0, 0,
|
||||
tgt_desc_len, seg_desc_len, 0);
|
||||
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_STATUS_GOOD);
|
||||
EXTENDEDCOPY(sd, &data, EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE,
|
||||
"Copy Status for the above Extended Copy command");
|
||||
RECEIVE_COPY_RESULTS(&cs_task, sd, SCSI_COPY_RESULTS_COPY_STATUS,
|
||||
logging(LOG_VERBOSE,
|
||||
"Copy Status for the above Extended Copy command");
|
||||
RECEIVE_COPY_RESULTS(&cs_task, sd, SCSI_COPY_RESULTS_COPY_STATUS,
|
||||
list_id, (void **)&csp, EXPECT_STATUS_GOOD);
|
||||
|
||||
scsi_free_scsi_task(cs_task);
|
||||
scsi_free_scsi_task(cs_task);
|
||||
}
|
||||
|
||||
@@ -30,19 +30,19 @@
|
||||
void
|
||||
test_receive_copy_results_op_params(void)
|
||||
{
|
||||
struct scsi_task *op_task = NULL;
|
||||
struct scsi_copy_results_op_params *opp;
|
||||
struct scsi_task *op_task = NULL;
|
||||
struct scsi_copy_results_op_params *opp;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test RECEIVE COPY RESULTS, OPERATING PARAMS");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test RECEIVE COPY RESULTS, OPERATING PARAMS");
|
||||
|
||||
RECEIVE_COPY_RESULTS(&op_task, sd, SCSI_COPY_RESULTS_OP_PARAMS, 0,
|
||||
RECEIVE_COPY_RESULTS(&op_task, sd, SCSI_COPY_RESULTS_OP_PARAMS, 0,
|
||||
(void **)&opp, EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_NORMAL,
|
||||
"max_target_desc=%d, max_seg_desc=%d",
|
||||
opp->max_target_desc_count,
|
||||
opp->max_segment_desc_count);
|
||||
logging(LOG_NORMAL,
|
||||
"max_target_desc=%d, max_seg_desc=%d",
|
||||
opp->max_target_desc_count,
|
||||
opp->max_segment_desc_count);
|
||||
|
||||
scsi_free_scsi_task(op_task);
|
||||
scsi_free_scsi_task(op_task);
|
||||
}
|
||||
|
||||
@@ -29,82 +29,82 @@
|
||||
void
|
||||
test_report_supported_opcodes_one_command(void)
|
||||
{
|
||||
int i;
|
||||
struct scsi_task *rso_task;
|
||||
struct scsi_task *one_task;
|
||||
struct scsi_report_supported_op_codes *rsoc;
|
||||
struct scsi_report_supported_op_codes_one_command *rsoc_one;
|
||||
int i;
|
||||
struct scsi_task *rso_task;
|
||||
struct scsi_task *one_task;
|
||||
struct scsi_report_supported_op_codes *rsoc;
|
||||
struct scsi_report_supported_op_codes_one_command *rsoc_one;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ_SUPPORTED_OPCODES reading one-command");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ_SUPPORTED_OPCODES reading one-command");
|
||||
|
||||
logging(LOG_VERBOSE, "Fetch list of all supported opcodes");
|
||||
REPORT_SUPPORTED_OPCODES(sd, &rso_task,
|
||||
logging(LOG_VERBOSE, "Fetch list of all supported opcodes");
|
||||
REPORT_SUPPORTED_OPCODES(sd, &rso_task,
|
||||
0, SCSI_REPORT_SUPPORTING_OPS_ALL,
|
||||
0, 0, 65535,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc);
|
||||
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify read one-command works for all supported "
|
||||
"opcodes");
|
||||
for (i = 0; i < rsoc->num_descriptors; i++) {
|
||||
logging(LOG_VERBOSE, "Check opcode:0x%02x ServiceAction:0x%02x",
|
||||
rsoc->descriptors[i].opcode,
|
||||
rsoc->descriptors[i].sa);
|
||||
if (rsoc->descriptors[i].servactv) {
|
||||
logging(LOG_VERBOSE, "This opcode has service actions. "
|
||||
"Reporting Options 001b should fail");
|
||||
REPORT_SUPPORTED_OPCODES(sd, NULL, 0,
|
||||
logging(LOG_VERBOSE, "Verify read one-command works for all supported "
|
||||
"opcodes");
|
||||
for (i = 0; i < rsoc->num_descriptors; i++) {
|
||||
logging(LOG_VERBOSE, "Check opcode:0x%02x ServiceAction:0x%02x",
|
||||
rsoc->descriptors[i].opcode,
|
||||
rsoc->descriptors[i].sa);
|
||||
if (rsoc->descriptors[i].servactv) {
|
||||
logging(LOG_VERBOSE, "This opcode has service actions. "
|
||||
"Reporting Options 001b should fail");
|
||||
REPORT_SUPPORTED_OPCODES(sd, NULL, 0,
|
||||
SCSI_REPORT_SUPPORTING_OPCODE,
|
||||
rsoc->descriptors[i].opcode,
|
||||
rsoc->descriptors[i].sa,
|
||||
65535,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "This opcode does not have "
|
||||
"service actions. Reporting Options 001b "
|
||||
"should work");
|
||||
REPORT_SUPPORTED_OPCODES(sd, NULL, 0,
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "This opcode does not have "
|
||||
"service actions. Reporting Options 001b "
|
||||
"should work");
|
||||
REPORT_SUPPORTED_OPCODES(sd, NULL, 0,
|
||||
SCSI_REPORT_SUPPORTING_OPCODE,
|
||||
rsoc->descriptors[i].opcode,
|
||||
rsoc->descriptors[i].sa,
|
||||
65535,
|
||||
EXPECT_STATUS_GOOD);
|
||||
}
|
||||
}
|
||||
|
||||
if (rsoc->descriptors[i].servactv) {
|
||||
logging(LOG_VERBOSE, "This opcode has service actions. "
|
||||
"Reporting Options 002b should work");
|
||||
REPORT_SUPPORTED_OPCODES(sd, NULL, 0,
|
||||
if (rsoc->descriptors[i].servactv) {
|
||||
logging(LOG_VERBOSE, "This opcode has service actions. "
|
||||
"Reporting Options 002b should work");
|
||||
REPORT_SUPPORTED_OPCODES(sd, NULL, 0,
|
||||
SCSI_REPORT_SUPPORTING_SERVICEACTION,
|
||||
rsoc->descriptors[i].opcode,
|
||||
rsoc->descriptors[i].sa,
|
||||
65535,
|
||||
EXPECT_STATUS_GOOD);
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "This opcode does not have "
|
||||
"service actions. Reporting Options 002b "
|
||||
"should fail");
|
||||
REPORT_SUPPORTED_OPCODES(sd, NULL, 0,
|
||||
} else {
|
||||
logging(LOG_VERBOSE, "This opcode does not have "
|
||||
"service actions. Reporting Options 002b "
|
||||
"should fail");
|
||||
REPORT_SUPPORTED_OPCODES(sd, NULL, 0,
|
||||
SCSI_REPORT_SUPPORTING_SERVICEACTION,
|
||||
rsoc->descriptors[i].opcode,
|
||||
rsoc->descriptors[i].sa,
|
||||
65535,
|
||||
EXPECT_INVALID_FIELD_IN_CDB);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Verify read one-command CDB looks sane");
|
||||
for (i = 0; i < rsoc->num_descriptors; i++) {
|
||||
logging(LOG_VERBOSE, "Check CDB for opcode:0x%02x "
|
||||
"ServiceAction:0x%02x",
|
||||
rsoc->descriptors[i].opcode,
|
||||
rsoc->descriptors[i].sa);
|
||||
REPORT_SUPPORTED_OPCODES(sd, &one_task, 0,
|
||||
logging(LOG_VERBOSE, "Verify read one-command CDB looks sane");
|
||||
for (i = 0; i < rsoc->num_descriptors; i++) {
|
||||
logging(LOG_VERBOSE, "Check CDB for opcode:0x%02x "
|
||||
"ServiceAction:0x%02x",
|
||||
rsoc->descriptors[i].opcode,
|
||||
rsoc->descriptors[i].sa);
|
||||
REPORT_SUPPORTED_OPCODES(sd, &one_task, 0,
|
||||
rsoc->descriptors[i].servactv ?
|
||||
SCSI_REPORT_SUPPORTING_SERVICEACTION :
|
||||
SCSI_REPORT_SUPPORTING_OPCODE,
|
||||
@@ -113,29 +113,29 @@ test_report_supported_opcodes_one_command(void)
|
||||
65535,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc_one = scsi_datain_unmarshall(one_task);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc_one);
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc_one = scsi_datain_unmarshall(one_task);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc_one);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify CDB length is not 0");
|
||||
CU_ASSERT_NOT_EQUAL(rsoc_one->cdb_length, 0);
|
||||
if (rsoc_one->cdb_length == 0) {
|
||||
logging(LOG_NORMAL, "[FAILED] CDB length is 0");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify CDB[0] Usage Data == <opcode>");
|
||||
CU_ASSERT_EQUAL(rsoc_one->cdb_usage_data[0],
|
||||
rsoc->descriptors[i].opcode);
|
||||
if (rsoc_one->cdb_usage_data[0] != rsoc->descriptors[i].opcode) {
|
||||
logging(LOG_NORMAL, "[FAILED] CDB[0] Usage Data was "
|
||||
"0x%02x, expected 0x%02x for opcode 0x%02x",
|
||||
rsoc_one->cdb_usage_data[0],
|
||||
rsoc->descriptors[i].opcode,
|
||||
rsoc->descriptors[i].opcode);
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify CDB length is not 0");
|
||||
CU_ASSERT_NOT_EQUAL(rsoc_one->cdb_length, 0);
|
||||
if (rsoc_one->cdb_length == 0) {
|
||||
logging(LOG_NORMAL, "[FAILED] CDB length is 0");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify CDB[0] Usage Data == <opcode>");
|
||||
CU_ASSERT_EQUAL(rsoc_one->cdb_usage_data[0],
|
||||
rsoc->descriptors[i].opcode);
|
||||
if (rsoc_one->cdb_usage_data[0] != rsoc->descriptors[i].opcode) {
|
||||
logging(LOG_NORMAL, "[FAILED] CDB[0] Usage Data was "
|
||||
"0x%02x, expected 0x%02x for opcode 0x%02x",
|
||||
rsoc_one->cdb_usage_data[0],
|
||||
rsoc->descriptors[i].opcode,
|
||||
rsoc->descriptors[i].opcode);
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(one_task);
|
||||
}
|
||||
scsi_free_scsi_task(one_task);
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(rso_task);
|
||||
scsi_free_scsi_task(rso_task);
|
||||
}
|
||||
|
||||
@@ -29,70 +29,70 @@
|
||||
void
|
||||
test_report_supported_opcodes_rctd(void)
|
||||
{
|
||||
int i;
|
||||
struct scsi_task *rso_task;
|
||||
struct scsi_report_supported_op_codes *rsoc;
|
||||
int i;
|
||||
struct scsi_task *rso_task;
|
||||
struct scsi_report_supported_op_codes *rsoc;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ_SUPPORTED_OPCODES RCTD flag");
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ_SUPPORTED_OPCODES RCTD flag");
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ_SUPPORTED_OPCODES report ALL opcodes "
|
||||
"without timeout descriptors. RCTD==0");
|
||||
REPORT_SUPPORTED_OPCODES(sd, &rso_task,
|
||||
logging(LOG_VERBOSE, "Test READ_SUPPORTED_OPCODES report ALL opcodes "
|
||||
"without timeout descriptors. RCTD==0");
|
||||
REPORT_SUPPORTED_OPCODES(sd, &rso_task,
|
||||
0, SCSI_REPORT_SUPPORTING_OPS_ALL, 0, 0,
|
||||
65535,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc);
|
||||
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that all returned command descriptors "
|
||||
"lack timeout description");
|
||||
for (i = 0; i < rsoc->num_descriptors; i++) {
|
||||
if (rsoc->descriptors[i].ctdp) {
|
||||
logging(LOG_NORMAL, "[FAILED] Command descriptor with "
|
||||
"CTDP set received when RCTD==0");
|
||||
CU_FAIL("[FAILED] Command descriptor with "
|
||||
"CTDP set");
|
||||
}
|
||||
}
|
||||
scsi_free_scsi_task(rso_task);
|
||||
logging(LOG_VERBOSE, "Verify that all returned command descriptors "
|
||||
"lack timeout description");
|
||||
for (i = 0; i < rsoc->num_descriptors; i++) {
|
||||
if (rsoc->descriptors[i].ctdp) {
|
||||
logging(LOG_NORMAL, "[FAILED] Command descriptor with "
|
||||
"CTDP set received when RCTD==0");
|
||||
CU_FAIL("[FAILED] Command descriptor with "
|
||||
"CTDP set");
|
||||
}
|
||||
}
|
||||
scsi_free_scsi_task(rso_task);
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ_SUPPORTED_OPCODES report ALL opcodes "
|
||||
"with timeout descriptors. RCTD==1");
|
||||
REPORT_SUPPORTED_OPCODES(sd, &rso_task,
|
||||
logging(LOG_VERBOSE, "Test READ_SUPPORTED_OPCODES report ALL opcodes "
|
||||
"with timeout descriptors. RCTD==1");
|
||||
REPORT_SUPPORTED_OPCODES(sd, &rso_task,
|
||||
1, SCSI_REPORT_SUPPORTING_OPS_ALL, 0, 0,
|
||||
65535,
|
||||
EXPECT_STATUS_GOOD);
|
||||
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_NOT_EQUAL(rsoc, NULL);
|
||||
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_NOT_EQUAL(rsoc, NULL);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that all returned command descriptors "
|
||||
"have a timeout description");
|
||||
for (i = 0; i < rsoc->num_descriptors; i++) {
|
||||
if (!rsoc->descriptors[i].ctdp) {
|
||||
logging(LOG_NORMAL, "[FAILED] Command descriptor "
|
||||
"with CTDP clear when RCTD==1");
|
||||
CU_FAIL("[FAILED] Command descriptor without "
|
||||
"CTDP set");
|
||||
}
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify that all returned command descriptors "
|
||||
"have a timeout description");
|
||||
for (i = 0; i < rsoc->num_descriptors; i++) {
|
||||
if (!rsoc->descriptors[i].ctdp) {
|
||||
logging(LOG_NORMAL, "[FAILED] Command descriptor "
|
||||
"with CTDP clear when RCTD==1");
|
||||
CU_FAIL("[FAILED] Command descriptor without "
|
||||
"CTDP set");
|
||||
}
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that all timeout descriptors have the "
|
||||
"correct length");
|
||||
for (i = 0; i < rsoc->num_descriptors; i++) {
|
||||
if (rsoc->descriptors[i].ctdp &&
|
||||
rsoc->descriptors[i].to.descriptor_length != 0x0a) {
|
||||
logging(LOG_NORMAL, "[FAILED] Command descriptor "
|
||||
"with invalid TimeoutDescriptor length");
|
||||
CU_FAIL("[FAILED] Command descriptor with "
|
||||
"invalid TimeoutDescriptor length");
|
||||
}
|
||||
}
|
||||
logging(LOG_VERBOSE, "Verify that all timeout descriptors have the "
|
||||
"correct length");
|
||||
for (i = 0; i < rsoc->num_descriptors; i++) {
|
||||
if (rsoc->descriptors[i].ctdp &&
|
||||
rsoc->descriptors[i].to.descriptor_length != 0x0a) {
|
||||
logging(LOG_NORMAL, "[FAILED] Command descriptor "
|
||||
"with invalid TimeoutDescriptor length");
|
||||
CU_FAIL("[FAILED] Command descriptor with "
|
||||
"invalid TimeoutDescriptor length");
|
||||
}
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(rso_task);
|
||||
scsi_free_scsi_task(rso_task);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user