Fix merge conflicts

This commit is contained in:
Jon Grimm
2012-10-01 09:48:03 -05:00
10 changed files with 560 additions and 89 deletions

View File

@@ -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 \

View File

@@ -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,

View File

@@ -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;

View File

@@ -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:

View File

@@ -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");

View 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;
}

View 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
View 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

View File

@@ -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 },

View File

@@ -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);