Fix merge conflicts
This commit is contained in:
@@ -135,6 +135,8 @@ bin_iscsi_test_SOURCES = test-tool/iscsi-test.c \
|
||||
test-tool/0404_inquiry_all_reported_vpd.c \
|
||||
test-tool/0410_readtoc_basic.c \
|
||||
test-tool/0420_reserve6_simple.c \
|
||||
test-tool/0421_reserve6_lun_reset.c \
|
||||
test-tool/0422_reserve6_logout.c \
|
||||
\
|
||||
test-tool/1000_cmdsn_invalid.c \
|
||||
test-tool/1010_datasn_invalid.c \
|
||||
|
||||
@@ -112,7 +112,7 @@ enum scsi_xfer_dir {
|
||||
/*
|
||||
* READTOC
|
||||
*/
|
||||
EXTERN struct scsi_task *scsi_cdb_readtoc(int msf, int format, int track_session, uint32_t xferlen);
|
||||
EXTERN struct scsi_task *scsi_cdb_readtoc(int msf, int format, int track_session, uint16_t alloc_len);
|
||||
|
||||
enum scsi_readtoc_fmt {
|
||||
SCSI_READ_TOC = 0,
|
||||
|
||||
@@ -308,7 +308,7 @@ scsi_cdb_readcapacity10(int lba, int pmi)
|
||||
* READTOC
|
||||
*/
|
||||
struct scsi_task *
|
||||
scsi_cdb_readtoc(int msf, int format, int track_session, uint32_t xferlen)
|
||||
scsi_cdb_readtoc(int msf, int format, int track_session, uint16_t alloc_len)
|
||||
{
|
||||
struct scsi_task *task;
|
||||
|
||||
@@ -335,13 +335,15 @@ scsi_cdb_readtoc(int msf, int format, int track_session, uint32_t xferlen)
|
||||
task->cdb[6] = 0xff & track_session;
|
||||
}
|
||||
|
||||
*(uint16_t *)&task->cdb[7] = htons(alloc_len);
|
||||
|
||||
task->cdb_size = 10;
|
||||
if (xferlen != 0) {
|
||||
if (alloc_len != 0) {
|
||||
task->xfer_dir = SCSI_XFER_READ;
|
||||
} else {
|
||||
task->xfer_dir = SCSI_XFER_NONE;
|
||||
}
|
||||
task->expxferlen = xferlen;
|
||||
task->expxferlen = alloc_len;
|
||||
|
||||
task->params.readtoc.msf = msf;
|
||||
task->params.readtoc.format = format;
|
||||
|
||||
@@ -29,16 +29,20 @@ int T0410_readtoc_basic(const char *initiator, const char *url, int data_loss, i
|
||||
struct scsi_inquiry_standard *inq;
|
||||
struct scsi_readcapacity10 *rc10;
|
||||
struct scsi_readtoc_list *list, *list1;
|
||||
int ret, lun, i, toc_device;
|
||||
int media, full_size;
|
||||
int ret, lun, i, toc_device, full_size;
|
||||
int is_blank = 0;
|
||||
int no_medium = 0;
|
||||
|
||||
printf("0410_readtoc_basic:\n");
|
||||
printf("===================\n");
|
||||
if (show_info) {
|
||||
printf("Test Read TOC command.\n");
|
||||
printf(" If device does not support, just verify appropriate error returned\n");
|
||||
printf("1, Check we can read the TOC: track 0, non-MSF.\n");
|
||||
printf("1, Verify we can read the TOC: track 0, non-MSF. (non-MMC devices should return sense)\n");
|
||||
printf("2, Make sure at least 4 bytes returned as header.\n");
|
||||
printf("3, Verify we can read the TOC: track 1, non-MSF.\n");
|
||||
printf("4, Make sure at least 4 bytes returned as header.\n");
|
||||
printf("5, Verify track 0 and 1 both returned the same data.\n");
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -52,6 +56,7 @@ int T0410_readtoc_basic(const char *initiator, const char *url, int data_loss, i
|
||||
|
||||
ret = 0;
|
||||
|
||||
|
||||
printf("Read standard INQUIRY data ... ");
|
||||
/* Submit INQUIRY so we can find out the device type */
|
||||
task = iscsi_inquiry_sync(iscsi, lun, 0, 0, 255);
|
||||
@@ -92,22 +97,25 @@ int T0410_readtoc_basic(const char *initiator, const char *url, int data_loss, i
|
||||
|
||||
printf("Check device-type is either of DISK, TAPE or CD/DVD ... ");
|
||||
switch (inq->device_type) {
|
||||
case SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_MMC:
|
||||
toc_device = 1;
|
||||
break;
|
||||
case SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS:
|
||||
case SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_SEQUENTIAL_ACCESS:
|
||||
toc_device = 0;
|
||||
break;
|
||||
case SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_MMC:
|
||||
toc_device = 1;
|
||||
break;
|
||||
default:
|
||||
printf("[FAILED]\n");
|
||||
printf("Device-type is not DISK, TAPE or CD/DVD. Device reported:%s\n", scsi_devtype_to_str(inq->device_type));
|
||||
ret = -1;
|
||||
/* Unknown device type */
|
||||
printf("[SKIPPED]\n");
|
||||
printf("This test is only available on SBC/SBC/SSC devices\n");
|
||||
ret = -2;
|
||||
goto finished;
|
||||
}
|
||||
scsi_free_scsi_task(task);
|
||||
printf("[OK]\n");
|
||||
|
||||
printf("CD/DVD Device. Check if media present.\n");
|
||||
|
||||
printf("CD/DVD Device. Check if medium present ... ");
|
||||
task = iscsi_readcapacity10_sync(iscsi, lun, 0, 0);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
@@ -115,108 +123,127 @@ int T0410_readtoc_basic(const char *initiator, const char *url, int data_loss, i
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
if (task->status == SCSI_STATUS_GOOD) {
|
||||
rc10 = scsi_datain_unmarshall(task);
|
||||
if (rc10 == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
printf("failed to unmarshall readcapacity10 data. %s\n", iscsi_get_error(iscsi));
|
||||
ret = -1;
|
||||
scsi_free_scsi_task(task);
|
||||
goto finished;
|
||||
}
|
||||
/* LBA will return 0, if the medium is blank. */
|
||||
is_blank = rc10->lba ? 0 : 1;
|
||||
}
|
||||
/* If we get 'medium not present' there is no medium in the drive */
|
||||
if (task->status == SCSI_STATUS_CHECK_CONDITION
|
||||
&& task->sense.key == SCSI_SENSE_NOT_READY
|
||||
&& (task->sense.ascq == SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT
|
||||
|| task->sense.ascq == SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_OPEN
|
||||
|| task->sense.ascq == SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_CLOSED)) {
|
||||
no_medium = 1;
|
||||
printf("[OK]\n");
|
||||
printf("No medium in drive. Medium access commands should fail\n");
|
||||
goto test1;
|
||||
} else if (task->status != SCSI_STATUS_GOOD) {
|
||||
printf("[FAILED]\n");
|
||||
printf("Readcapacity command: failed with sense. %s\n", iscsi_get_error(iscsi));
|
||||
ret = -1;
|
||||
scsi_free_scsi_task(task);
|
||||
goto finished;
|
||||
}
|
||||
rc10 = scsi_datain_unmarshall(task);
|
||||
if (rc10 == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
printf("failed to unmarshall readcapacity10 data. %s\n", iscsi_get_error(iscsi));
|
||||
ret = -1;
|
||||
scsi_free_scsi_task(task);
|
||||
goto finished;
|
||||
|
||||
scsi_free_scsi_task(task);
|
||||
|
||||
printf("[OK]\n");
|
||||
if (is_blank) {
|
||||
printf("Blank disk loaded. ReadTOC should fail.\n");
|
||||
} else {
|
||||
printf("There is a disk in the drive. ReadTOC should work.\n");
|
||||
}
|
||||
|
||||
/* LBA will return 0, if there is no media. */
|
||||
media = rc10->lba ? 1 : 0;
|
||||
|
||||
|
||||
test1:
|
||||
|
||||
printf("Read TOC format 0000b (TOC)\n");
|
||||
if (toc_device) {
|
||||
printf(" On MMC Device\n");
|
||||
} else {
|
||||
printf(" On non-MMC Device\n");
|
||||
}
|
||||
printf("Verify we can READTOC format 0000b (TOC) track 0 (%s) ... ",
|
||||
toc_device ? "On MMC Device" : "On non-MMC Device"
|
||||
);
|
||||
|
||||
task = iscsi_readtoc_sync(iscsi, lun, 0, 0, 0, 255);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
printf("Failed to send READ TOC command : %s\n", iscsi_get_error(iscsi));
|
||||
printf("Failed to send READTOC command : %s\n", iscsi_get_error(iscsi));
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
|
||||
|
||||
/* If no medium, just check if we have appropriate error and bail. */
|
||||
if (no_medium) {
|
||||
if (task->status == SCSI_STATUS_GOOD) {
|
||||
printf("[FAILED]\n");
|
||||
printf("READTOC Should have failed since no medium is loaded.\n");
|
||||
scsi_free_scsi_task(task);
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
|
||||
if (task->status != SCSI_STATUS_CHECK_CONDITION
|
||||
|| task->sense.key != SCSI_SENSE_NOT_READY
|
||||
|| (task->sense.ascq != SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT && task->sense.ascq != SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_OPEN
|
||||
&& task->sense.ascq != SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_CLOSED)) {
|
||||
printf("[FAILED]\n");
|
||||
printf("READTOC failed but ascq was wrong. Should "
|
||||
"have failed with MEDIUM_NOT_PRESENT. "
|
||||
"Sense:%s\n", iscsi_get_error(iscsi));
|
||||
scsi_free_scsi_task(task);
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
|
||||
printf("[OK]\n");
|
||||
printf("No disk, we got the correct sense code that medium is not present. Skipping the remainder of the test\n");
|
||||
scsi_free_scsi_task(task);
|
||||
goto finished;
|
||||
}
|
||||
|
||||
|
||||
/* If this is a non-MMC device, just verify that that comand failed
|
||||
as expected and then bail */
|
||||
if (!toc_device) {
|
||||
if (task->status == SCSI_STATUS_GOOD) {
|
||||
printf("[FAILED]\n");
|
||||
printf("READ TOC Should have failed\n");
|
||||
printf("READTOC Should have failed\n");
|
||||
ret = -1;
|
||||
} else if (task->status != SCSI_STATUS_CHECK_CONDITION
|
||||
|| task->sense.key != SCSI_SENSE_ILLEGAL_REQUEST
|
||||
|| task->sense.ascq != SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
|
||||
printf("[FAILED]\n");
|
||||
printf("READ TOC failed but ascq was wrong. Should have failed with ILLEGAL_REQUEST/INVALID OPERATOR. Sense:%s\n", iscsi_get_error(iscsi));
|
||||
ret = -1;
|
||||
} else {
|
||||
printf("[OK]\n");
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(task);
|
||||
goto finished;
|
||||
}
|
||||
|
||||
|
||||
/* If no media, just check if we have appropriate error and bail. */
|
||||
if (!media) {
|
||||
printf("No media, check we get appropriate error.\n");
|
||||
if (task->status == SCSI_STATUS_GOOD) {
|
||||
printf("[FAILED]\n");
|
||||
printf("READ TOC Should have failed\n");
|
||||
printf("READTOC failed but ascq was wrong. Should have failed with ILLEGAL_REQUEST/INVALID OPERATION_CODE. Sense:%s\n", iscsi_get_error(iscsi));
|
||||
ret = -1;
|
||||
} else if (task->status != SCSI_STATUS_CHECK_CONDITION
|
||||
|| task->sense.key != SCSI_SENSE_NOT_READY
|
||||
|| (task->sense.ascq
|
||||
!= SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT
|
||||
&& task->sense.ascq
|
||||
!= SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_OPEN
|
||||
&& task->sense.ascq
|
||||
!= SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_CLOSED)) {
|
||||
printf("[FAILED]\n");
|
||||
printf("READ TOC failed but ascq was wrong. Should "
|
||||
"have failed with MEDIUM_NOT_PRESENT. "
|
||||
"Sense:%s\n", iscsi_get_error(iscsi));
|
||||
ret = -1;
|
||||
} else {
|
||||
printf("[OK]\n");
|
||||
ret = 0;
|
||||
printf("Not an MMC device so READTOC failed as it should. Skipping rest of test\n");
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(task);
|
||||
goto finished;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* We should only still be here if we are an MMC device and
|
||||
have media. */
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
printf("[FAILED]\n");
|
||||
printf("READ TOC command failed : %s\n", iscsi_get_error(iscsi));
|
||||
printf("READTOC command failed : %s\n", iscsi_get_error(iscsi));
|
||||
scsi_free_scsi_task(task);
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
printf("[OK]\n");
|
||||
|
||||
|
||||
|
||||
test2:
|
||||
/* If we get here, there is a disk loaded and it contains data */
|
||||
printf("Verify we got at least 4 bytes of data for track 0 ... ");
|
||||
full_size = scsi_datain_getfullsize(task);
|
||||
if (full_size < 4) {
|
||||
printf("[FAILED]\n");
|
||||
@@ -235,12 +262,13 @@ test2:
|
||||
}
|
||||
printf("[OK]\n");
|
||||
|
||||
|
||||
test3:
|
||||
printf("Check lba of 1 is same as lba 0\n");
|
||||
printf("Verify we can READTOC format 0000b (TOC) track 1 ... ");
|
||||
task1 = iscsi_readtoc_sync(iscsi, lun, 0, 1, 0, 255);
|
||||
if (task1 == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
printf("Failed to send READ TOC command : %s\n", iscsi_get_error(iscsi));
|
||||
printf("Failed to send READTOC command : %s\n", iscsi_get_error(iscsi));
|
||||
scsi_free_scsi_task(task);
|
||||
ret = -1;
|
||||
goto finished;
|
||||
@@ -248,14 +276,17 @@ test3:
|
||||
|
||||
if (task1->status != SCSI_STATUS_GOOD) {
|
||||
printf("[FAILED]\n");
|
||||
printf("READ TOC command failed : %s\n", iscsi_get_error(iscsi));
|
||||
printf("READTOC command failed : %s\n", iscsi_get_error(iscsi));
|
||||
scsi_free_scsi_task(task);
|
||||
scsi_free_scsi_task(task1);
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
printf("[OK]\n");
|
||||
|
||||
|
||||
test4:
|
||||
printf("Verify we got at least 4 bytes of data for track 1 ... ");
|
||||
full_size = scsi_datain_getfullsize(task1);
|
||||
if (full_size < 4) {
|
||||
printf("[FAILED]\n");
|
||||
@@ -274,8 +305,10 @@ test3:
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
scsi_free_scsi_task(task1);
|
||||
printf("[OK]\n");
|
||||
|
||||
test5:
|
||||
printf("Verify track 0 and 1 both returned the same data ... ");
|
||||
if (list->num != list1->num ||
|
||||
list->first != list1->first ||
|
||||
list->last != list1->last) {
|
||||
@@ -283,11 +316,11 @@ test3:
|
||||
printf("Read TOC header of lba 0 != TOC of lba 1.\n");
|
||||
ret = -1;
|
||||
scsi_free_scsi_task(task);
|
||||
scsi_free_scsi_task(task1);
|
||||
goto finished;
|
||||
}
|
||||
|
||||
for (i=0; i<list->num; i++) {
|
||||
printf(" TOC descriptor %i\n", i);
|
||||
if (list->desc[i].desc.toc.adr != list1->desc[i].desc.toc.adr ||
|
||||
list->desc[i].desc.toc.control != list1->desc[i].desc.toc.control ||
|
||||
list->desc[i].desc.toc.track != list1->desc[i].desc.toc.track ||
|
||||
@@ -296,13 +329,13 @@ test3:
|
||||
printf("Read TOC descriptors of lba 0 != TOC of lba 1.\n");
|
||||
ret = -1;
|
||||
scsi_free_scsi_task(task);
|
||||
scsi_free_scsi_task(task1);
|
||||
goto finished;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
printf("[OK]\n");
|
||||
scsi_free_scsi_task(task);
|
||||
scsi_free_scsi_task(task1);
|
||||
|
||||
|
||||
finished:
|
||||
|
||||
@@ -51,7 +51,7 @@ int T0420_reserve6_simple(const char *initiator, const char *url, int data_loss,
|
||||
return -1;
|
||||
}
|
||||
|
||||
iscsi2 = iscsi_context_login(initiator, url, &lun);
|
||||
iscsi2 = iscsi_context_login(initiator2, url, &lun);
|
||||
if (iscsi2 == NULL) {
|
||||
printf("Failed to login to target\n");
|
||||
ret = 1;
|
||||
@@ -60,7 +60,7 @@ int T0420_reserve6_simple(const char *initiator, const char *url, int data_loss,
|
||||
|
||||
ret = 0;
|
||||
|
||||
printf("Send RESERVE6...\n");
|
||||
printf("Send RESERVE6 ... ");
|
||||
task = iscsi_reserve6_sync(iscsi, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
@@ -89,7 +89,7 @@ int T0420_reserve6_simple(const char *initiator, const char *url, int data_loss,
|
||||
scsi_free_scsi_task(task);
|
||||
printf("[OK]\n");
|
||||
|
||||
printf("Send RELEASE6...\n");
|
||||
printf("Send RELEASE6 ... ");
|
||||
task = iscsi_release6_sync(iscsi, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
@@ -108,9 +108,10 @@ int T0420_reserve6_simple(const char *initiator, const char *url, int data_loss,
|
||||
scsi_free_scsi_task(task);
|
||||
printf("[OK]\n");
|
||||
|
||||
|
||||
test2:
|
||||
printf("Test that reservation works.\n");
|
||||
printf("Send RESERVE6 from Initiator 1...\n");
|
||||
printf("Send RESERVE6 from Initiator 1. ... ");
|
||||
task = iscsi_reserve6_sync(iscsi, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
@@ -129,7 +130,6 @@ test2:
|
||||
scsi_free_scsi_task(task);
|
||||
printf("[OK]\n");
|
||||
|
||||
printf("Send another RESERVE6 from Initiator 1...\n");
|
||||
task = iscsi_reserve6_sync(iscsi, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
@@ -149,7 +149,7 @@ test2:
|
||||
printf("[OK]\n");
|
||||
|
||||
test3:
|
||||
printf("Send RESERVE6 from Initiator 2...Expect conflict.\n");
|
||||
printf("Send RESERVE6 from Initiator 2. Expect conflict. ... ");
|
||||
task = iscsi_reserve6_sync(iscsi2, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
@@ -169,7 +169,7 @@ test3:
|
||||
printf("[OK]\n");
|
||||
|
||||
test3a:
|
||||
printf("Send RELEASE6 from Initiator 2..Expect NO-OP.\n");
|
||||
printf("Send RELEASE6 from Initiator 2..Expect NO-OP. ... ");
|
||||
task = iscsi_release6_sync(iscsi2, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
@@ -192,7 +192,7 @@ test3a:
|
||||
printf("[OK]\n");
|
||||
|
||||
test4:
|
||||
printf("Send TESTUNITREADY from Initiator 1...\n");
|
||||
printf("Send TESTUNITREADY from Initiator 1 ... ");
|
||||
task = iscsi_testunitready_sync(iscsi, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
@@ -212,7 +212,7 @@ test4:
|
||||
printf("[OK]\n");
|
||||
|
||||
test5:
|
||||
printf("Send TESTUNITREADY from Initiator 2...Expect conflict.\n");
|
||||
printf("Send TESTUNITREADY from Initiator 2. Expect conflict. ... ");
|
||||
task = iscsi_testunitready_sync(iscsi2, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
@@ -232,7 +232,7 @@ test5:
|
||||
|
||||
test6:
|
||||
printf("Test that release actually works\n");
|
||||
printf("Send RELEASE6 from Initiator 1...\n");
|
||||
printf("Send RELEASE6 from Initiator 1 ... ");
|
||||
task = iscsi_release6_sync(iscsi, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
@@ -251,7 +251,7 @@ test6:
|
||||
scsi_free_scsi_task(task);
|
||||
printf("[OK]\n");
|
||||
|
||||
printf("Send RESERVE6 Initiator 2...\n");
|
||||
printf("Send RESERVE6 Initiator 2 ... ");
|
||||
task = iscsi_reserve6_sync(iscsi2, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
@@ -270,7 +270,7 @@ test6:
|
||||
scsi_free_scsi_task(task);
|
||||
printf("[OK]\n");
|
||||
|
||||
printf("Send RELEASE6 Initiator 2...\n");
|
||||
printf("Send RELEASE6 Initiator 2 ... ");
|
||||
task = iscsi_reserve6_sync(iscsi2, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
|
||||
212
test-tool/0421_reserve6_lun_reset.c
Normal file
212
test-tool/0421_reserve6_lun_reset.c
Normal file
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
Copyright (C) 2012 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <poll.h>
|
||||
#include "iscsi.h"
|
||||
#include "scsi-lowlevel.h"
|
||||
#include "iscsi-test.h"
|
||||
|
||||
struct mgmt_task {
|
||||
uint32_t status;
|
||||
uint32_t finished;
|
||||
};
|
||||
|
||||
static void mgmt_cb(struct iscsi_context *iscsi _U_, int status _U_,
|
||||
void *command_data, void *private_data)
|
||||
{
|
||||
struct mgmt_task *mgmt_task = (struct mgmt_task *)private_data;
|
||||
|
||||
mgmt_task->status = *(uint32_t *)command_data;
|
||||
mgmt_task->finished = 1;
|
||||
}
|
||||
|
||||
int T0421_reserve6_lun_reset(const char *initiator, const char *url, int data_loss, int show_info)
|
||||
{
|
||||
struct iscsi_context *iscsi, *iscsi2;
|
||||
struct scsi_task *task;
|
||||
int ret, lun;
|
||||
struct mgmt_task mgmt_task = {0, 0};
|
||||
struct pollfd pfd;
|
||||
|
||||
printf("0421_reserve6_lun_reset:\n");
|
||||
printf("========================\n");
|
||||
if (show_info) {
|
||||
printf("Test that a RESERVE6 is dropped by a LUN-reset\n");
|
||||
printf(" If device does not support RESERVE6, just skip the test.\n");
|
||||
printf("1, Reserve the device from the first initiator.\n");
|
||||
printf("2, Verify we can access the LUN from the first initiator\n");
|
||||
printf("3, Verify we can NOT access the LUN from the second initiator\n");
|
||||
printf("4, Send a LUN-reset to the target\n");
|
||||
printf("5, Verify we can access the LUN from the second initiator\n");
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
iscsi = iscsi_context_login(initiator, url, &lun);
|
||||
if (iscsi == NULL) {
|
||||
printf("Failed to login to target\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
iscsi2 = iscsi_context_login(initiator2, url, &lun);
|
||||
if (iscsi2 == NULL) {
|
||||
printf("Failed to login to target\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
printf("Send RESERVE6 from the first initiator ... ");
|
||||
task = iscsi_reserve6_sync(iscsi, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
printf("Failed to send RESERVE6 command : %s\n",
|
||||
iscsi_get_error(iscsi));
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
if (task->status == SCSI_STATUS_CHECK_CONDITION
|
||||
&& task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST
|
||||
&& task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
|
||||
printf("[SKIPPED]\n");
|
||||
printf("RESERVE6 Not Supported\n");
|
||||
ret = -2;
|
||||
scsi_free_scsi_task(task);
|
||||
goto finished;
|
||||
}
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
printf("[FAILED]\n");
|
||||
printf("RESERVE6 failed with sense:%s\n",
|
||||
iscsi_get_error(iscsi));
|
||||
ret = -1;
|
||||
scsi_free_scsi_task(task);
|
||||
goto test2;
|
||||
}
|
||||
scsi_free_scsi_task(task);
|
||||
printf("[OK]\n");
|
||||
|
||||
|
||||
test2:
|
||||
printf("Verify we can access the LUN from the first initiator ... ");
|
||||
task = iscsi_testunitready_sync(iscsi, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
printf("Failed to send TEST UNIT READY command: %s\n",
|
||||
iscsi_get_error(iscsi));
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
printf("[FAILED]\n");
|
||||
printf("TEST UNIT READY command: failed with sense %s\n",
|
||||
iscsi_get_error(iscsi));
|
||||
ret = -1;
|
||||
scsi_free_scsi_task(task);
|
||||
goto test3;
|
||||
}
|
||||
scsi_free_scsi_task(task);
|
||||
printf("[OK]\n");
|
||||
|
||||
|
||||
test3:
|
||||
printf("Verify we can NOT access the LUN from the second initiator ... ");
|
||||
task = iscsi_testunitready_sync(iscsi2, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
printf("Failed to send TEST UNIT READY command: %s\n",
|
||||
iscsi_get_error(iscsi2));
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
if (task->status != SCSI_STATUS_RESERVATION_CONFLICT) {
|
||||
printf("[FAILED]\n");
|
||||
printf("Expected RESERVATION CONFLICT\n");
|
||||
ret = -1;
|
||||
scsi_free_scsi_task(task);
|
||||
goto finished;
|
||||
}
|
||||
scsi_free_scsi_task(task);
|
||||
printf("[OK]\n");
|
||||
|
||||
test4:
|
||||
printf("Send a LUN Reset to the target ... ");
|
||||
iscsi_task_mgmt_lun_reset_async(iscsi, lun, mgmt_cb, &mgmt_task);
|
||||
while (mgmt_task.finished == 0) {
|
||||
pfd.fd = iscsi_get_fd(iscsi);
|
||||
pfd.events = iscsi_which_events(iscsi);
|
||||
|
||||
if (poll(&pfd, 1, -1) < 0) {
|
||||
printf("Poll failed");
|
||||
goto finished;
|
||||
}
|
||||
if (iscsi_service(iscsi, pfd.revents) < 0) {
|
||||
printf("iscsi_service failed with : %s\n", iscsi_get_error(iscsi));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mgmt_task.status != 0) {
|
||||
printf("[FAILED]\n");
|
||||
printf("Failed to reset the LUN\n");
|
||||
goto finished;
|
||||
}
|
||||
printf("[OK]\n");
|
||||
|
||||
test5:
|
||||
/* We might be getting UNIT_ATTENTION/BUS_RESET after the lun-reset above.
|
||||
If so just loop and try the TESTUNITREADY again until it clears
|
||||
*/
|
||||
printf("Verify we can access the LUN from the second initiator ... ");
|
||||
task = iscsi_testunitready_sync(iscsi2, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
printf("Failed to send TEST UNIT READY command: %s\n",
|
||||
iscsi_get_error(iscsi2));
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
if (task->status == SCSI_STATUS_CHECK_CONDITION
|
||||
&& task->sense.key == SCSI_SENSE_UNIT_ATTENTION
|
||||
&& task->sense.ascq == SCSI_SENSE_ASCQ_BUS_RESET) {
|
||||
printf("Got BUS RESET. Retry accessing the LUN\n");
|
||||
goto test5;
|
||||
|
||||
}
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
printf("[FAILED]\n");
|
||||
printf("TEST UNIT READY command: failed with sense %s\n",
|
||||
iscsi_get_error(iscsi2));
|
||||
ret = -1;
|
||||
scsi_free_scsi_task(task);
|
||||
goto test3;
|
||||
}
|
||||
scsi_free_scsi_task(task);
|
||||
printf("[OK]\n");
|
||||
|
||||
|
||||
finished:
|
||||
iscsi_logout_sync(iscsi);
|
||||
iscsi_destroy_context(iscsi);
|
||||
iscsi_logout_sync(iscsi2);
|
||||
iscsi_destroy_context(iscsi2);
|
||||
return ret;
|
||||
}
|
||||
166
test-tool/0422_reserve6_logout.c
Normal file
166
test-tool/0422_reserve6_logout.c
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
Copyright (C) 2012 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "iscsi.h"
|
||||
#include "scsi-lowlevel.h"
|
||||
#include "iscsi-test.h"
|
||||
|
||||
int T0422_reserve6_logout(const char *initiator, const char *url, int data_loss, int show_info)
|
||||
{
|
||||
struct iscsi_context *iscsi, *iscsi2;
|
||||
struct scsi_task *task;
|
||||
int ret, lun;
|
||||
|
||||
printf("0422_reserve6_logout:\n");
|
||||
printf("=====================\n");
|
||||
if (show_info) {
|
||||
printf("Test that a RESERVE6 is dropped when the session is logged out\n");
|
||||
printf(" If device does not support RESERVE6, just skip the test.\n");
|
||||
printf("1, Reserve the device from the first initiator.\n");
|
||||
printf("2, Verify we can access the LUN from the first initiator.\n");
|
||||
printf("3, Verify we can NOT access the LUN from the second initiator.\n");
|
||||
printf("4, Logout the first initiator.\n");
|
||||
printf("5, Verify we can access the LUN from the second initiator.\n");
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
iscsi = iscsi_context_login(initiator, url, &lun);
|
||||
if (iscsi == NULL) {
|
||||
printf("Failed to login to target\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
iscsi2 = iscsi_context_login(initiator2, url, &lun);
|
||||
if (iscsi2 == NULL) {
|
||||
printf("Failed to login to target\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
printf("Send RESERVE6 from the first initiator ... ");
|
||||
task = iscsi_reserve6_sync(iscsi, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
printf("Failed to send RESERVE6 command : %s\n",
|
||||
iscsi_get_error(iscsi));
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
if (task->status == SCSI_STATUS_CHECK_CONDITION
|
||||
&& task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST
|
||||
&& task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
|
||||
printf("[SKIPPED]\n");
|
||||
printf("RESERVE6 Not Supported\n");
|
||||
ret = -2;
|
||||
scsi_free_scsi_task(task);
|
||||
goto finished;
|
||||
}
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
printf("[FAILED]\n");
|
||||
printf("RESERVE6 failed with sense:%s\n",
|
||||
iscsi_get_error(iscsi));
|
||||
ret = -1;
|
||||
scsi_free_scsi_task(task);
|
||||
goto test2;
|
||||
}
|
||||
scsi_free_scsi_task(task);
|
||||
printf("[OK]\n");
|
||||
|
||||
|
||||
test2:
|
||||
printf("Verify we can access the LUN from the first initiator ... ");
|
||||
task = iscsi_testunitready_sync(iscsi, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
printf("Failed to send TEST UNIT READY command: %s\n",
|
||||
iscsi_get_error(iscsi));
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
printf("[FAILED]\n");
|
||||
printf("TEST UNIT READY command: failed with sense %s\n",
|
||||
iscsi_get_error(iscsi));
|
||||
ret = -1;
|
||||
scsi_free_scsi_task(task);
|
||||
goto test3;
|
||||
}
|
||||
scsi_free_scsi_task(task);
|
||||
printf("[OK]\n");
|
||||
|
||||
|
||||
test3:
|
||||
printf("Verify we can NOT access the LUN from the second initiator ... ");
|
||||
task = iscsi_testunitready_sync(iscsi2, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
printf("Failed to send TEST UNIT READY command: %s\n",
|
||||
iscsi_get_error(iscsi2));
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
if (task->status != SCSI_STATUS_RESERVATION_CONFLICT) {
|
||||
printf("[FAILED]\n");
|
||||
printf("Expected RESERVATION CONFLICT\n");
|
||||
ret = -1;
|
||||
scsi_free_scsi_task(task);
|
||||
goto finished;
|
||||
}
|
||||
scsi_free_scsi_task(task);
|
||||
printf("[OK]\n");
|
||||
|
||||
test4:
|
||||
printf("Logout the first initiator ... ");
|
||||
iscsi_logout_sync(iscsi);
|
||||
iscsi_destroy_context(iscsi);
|
||||
printf("[OK]\n");
|
||||
|
||||
test5:
|
||||
printf("Verify we can access the LUN from the second initiator ... ");
|
||||
task = iscsi_testunitready_sync(iscsi2, lun);
|
||||
if (task == NULL) {
|
||||
printf("[FAILED]\n");
|
||||
printf("Failed to send TEST UNIT READY command: %s\n",
|
||||
iscsi_get_error(iscsi2));
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
printf("[FAILED]\n");
|
||||
printf("TEST UNIT READY command: failed with sense %s\n",
|
||||
iscsi_get_error(iscsi2));
|
||||
ret = -1;
|
||||
scsi_free_scsi_task(task);
|
||||
goto finished;
|
||||
}
|
||||
scsi_free_scsi_task(task);
|
||||
printf("[OK]\n");
|
||||
|
||||
|
||||
finished:
|
||||
iscsi_logout_sync(iscsi2);
|
||||
iscsi_destroy_context(iscsi2);
|
||||
return ret;
|
||||
}
|
||||
45
test-tool/README
Normal file
45
test-tool/README
Normal file
@@ -0,0 +1,45 @@
|
||||
This directory contains a libiscsi based test tool.
|
||||
The purpose of this test tool is to validate iscsi and scsi protocol compliance of a target.
|
||||
|
||||
|
||||
Initiatornames and LUN-masking
|
||||
==============================
|
||||
If the target uses lun-masking or ACLs you need to set the target up to allow
|
||||
iscsi-test access to the LUNs you want to test.
|
||||
By default iscsi-test uses the following two initiator names :
|
||||
iqn.2007-10.com.github:sahlberg:libiscsi:iscsi-test
|
||||
iqn.2007-10.com.github:sahlberg:libiscsi:iscsi-test-2
|
||||
|
||||
Most tests only use the first name but some tests, such as the RESERVE/RELEASE
|
||||
tests, will use both names.
|
||||
|
||||
Optionally you can use different initiatir names for your testing using the
|
||||
command line flags :
|
||||
--initiator-name=iqn.<some other name>
|
||||
--initiator-name-2=iqn.<another different name>
|
||||
|
||||
|
||||
Listing all tests and test details:
|
||||
===================================
|
||||
The --list argument is used to show a lost of all major tests that are available
|
||||
iscsi-test --list
|
||||
|
||||
To list all tests and a description of each test and subtests, use
|
||||
iscsi-test --list --info
|
||||
|
||||
Running tests:
|
||||
==============
|
||||
Running tests you need to specify which test to run using the --test argument.
|
||||
This can either be the name of one specific test or a set of tests using * as
|
||||
the wildcard character.
|
||||
|
||||
Example to run one specific test :
|
||||
iscsi-test --test="T1020_bufferoffset_invalid" iscsi://127.0.0.1/iqn.ronnie.test/1
|
||||
|
||||
Example to run all READ10 tests :
|
||||
iscsi-test --test="*read10*" iscsi://127.0.0.1/iqn.ronnie.test/1
|
||||
|
||||
Or to run every test :
|
||||
iscsi-test --test="*" iscsi://127.0.0.1/iqn.ronnie.test/1
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#include "iscsi-test.h"
|
||||
|
||||
const char *initiator = "iqn.2007-10.com.github:sahlberg:libiscsi:iscsi-test";
|
||||
const char *initiator2 = "iqn.2007-10.com.github:sahlberg:libiscsi:iscsi-test-2";
|
||||
|
||||
static int data_loss = 0;
|
||||
static int show_info = 0;
|
||||
|
||||
@@ -216,6 +218,8 @@ struct scsi_test tests[] = {
|
||||
|
||||
/* reserve6/release6 */
|
||||
{ "T0420_reserve6_simple", T0420_reserve6_simple },
|
||||
{ "T0421_reserve6_lun_reset", T0421_reserve6_lun_reset },
|
||||
{ "T0422_reserve6_logout", T0422_reserve6_logout },
|
||||
|
||||
/* iSCSI protocol tests */
|
||||
|
||||
@@ -242,6 +246,7 @@ void print_help(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: iscsi-test [OPTION...] <iscsi-url>\n");
|
||||
fprintf(stderr, " -i, --initiator-name=iqn-name Initiatorname to use\n");
|
||||
fprintf(stderr, " -I, --initiator-name-2=iqn-name Second initiatorname to use\n");
|
||||
fprintf(stderr, " -t, --test=test-name Which test to run. Default is to run all tests.\n");
|
||||
fprintf(stderr, " -l, --list List all tests.\n");
|
||||
fprintf(stderr, " --info, Print extra info about a test.\n");
|
||||
@@ -372,6 +377,7 @@ int main(int argc, const char *argv[])
|
||||
{ "usage", 0, POPT_ARG_NONE, &show_usage, 0, "Display brief usage message", NULL },
|
||||
{ "list", 'l', POPT_ARG_NONE, &list_tests, 0, "List all tests", NULL },
|
||||
{ "initiator-name", 'i', POPT_ARG_STRING, &initiator, 0, "Initiatorname to use", "iqn-name" },
|
||||
{ "initiator-name-2", 'I', POPT_ARG_STRING, &initiator, 0, "Second initiatorname to use for tests using more two sessions", "iqn-name" },
|
||||
{ "test", 't', POPT_ARG_STRING, &testname, 0, "Which test to run", "testname" },
|
||||
{ "info", 0, POPT_ARG_NONE, &show_info, 0, "Show information about the test", "testname" },
|
||||
{ "dataloss", 0, POPT_ARG_NONE, &data_loss, 0, "Allow destructuve tests", NULL },
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
extern const char *initiator;
|
||||
extern const char *initiator2;
|
||||
|
||||
struct iscsi_context *iscsi_context_login(const char *initiatorname, const char *url, int *lun);
|
||||
|
||||
struct iscsi_async_state {
|
||||
@@ -167,6 +170,8 @@ int T0404_inquiry_all_reported_vpd(const char *initiator, const char *url, int d
|
||||
int T0410_readtoc_basic(const char *initiator, const char *url, int data_loss, int show_info);
|
||||
|
||||
int T0420_reserve6_simple(const char *initiator, const char *url, int data_loss, int show_info);
|
||||
int T0421_reserve6_lun_reset(const char *initiator, const char *url, int data_loss, int show_info);
|
||||
int T0422_reserve6_logout(const char *initiator, const char *url, int data_loss, int show_info);
|
||||
|
||||
int T1000_cmdsn_invalid(const char *initiator, const char *url, int data_loss, int show_info);
|
||||
int T1010_datasn_invalid(const char *initiator, const char *url, int data_loss, int show_info);
|
||||
|
||||
Reference in New Issue
Block a user