diff --git a/Makefile.am b/Makefile.am index 3308d9f..01af7bf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -190,6 +190,7 @@ bin_iscsi_test_cu_SOURCES = test-tool/iscsi-test-cu.c \ test-tool/test_inquiry_evpd.c \ test-tool/test_inquiry_supported_vpd.c \ test-tool/test_inquiry_mandatory_vpd_sbc.c \ + test-tool/test_iscsi_cmdsn_invalid.c \ test-tool/test_mandatory_sbc.c \ test-tool/test_nomedia_sbc.c \ test-tool/test_orwrite_simple.c \ diff --git a/include/iscsi-private.h b/include/iscsi-private.h index 9345b09..91e5f38 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -131,7 +131,8 @@ struct iscsi_context { int reallocs; int frees; - time_t last_reconnect; + time_t last_reconnect; + int scsi_timeout; }; #define ISCSI_PDU_IMMEDIATE 0x40 @@ -224,6 +225,7 @@ struct iscsi_pdu { struct iscsi_data indata; struct iscsi_scsi_cbdata scsi_cbdata; + time_t scsi_timeout; }; struct iscsi_pdu *iscsi_allocate_pdu(struct iscsi_context *iscsi, @@ -326,6 +328,8 @@ iscsi_serial32_compare(uint32_t s1, uint32_t s2); u_int32_t iscsi_itt_post_increment(struct iscsi_context *iscsi); +void iscsi_timeout_scan(struct iscsi_context *iscsi); + #ifdef __cplusplus } #endif diff --git a/include/iscsi.h b/include/iscsi.h index 98cdf5d..26cef0f 100644 --- a/include/iscsi.h +++ b/include/iscsi.h @@ -70,11 +70,18 @@ EXTERN int iscsi_service(struct iscsi_context *iscsi, int revents); */ EXTERN int iscsi_queue_length(struct iscsi_context *iscsi); +/* + * Set the timeout in seconds after which a synchronous SCSI command + * will timeout. + * Default is 0 == no timeout. + */ +EXTERN int iscsi_set_timeout(struct iscsi_context *iscsi, int timeout); + /* * To set tcp keepalive for the session. * Only options supported by given platform (if any) are set. */ -int iscsi_set_tcp_keepalive(struct iscsi_context *iscsi, int idle, int count, int interval); +EXTERN int iscsi_set_tcp_keepalive(struct iscsi_context *iscsi, int idle, int count, int interval); struct iscsi_url { char portal[MAX_STRING_SIZE+1]; @@ -268,7 +275,8 @@ enum scsi_status { SCSI_STATUS_RESERVATION_CONFLICT = 0x18, SCSI_STATUS_REDIRECT = 0x101, SCSI_STATUS_CANCELLED = 0x0f000000, - SCSI_STATUS_ERROR = 0x0f000001 + SCSI_STATUS_ERROR = 0x0f000001, + SCSI_STATUS_TIMEOUT = 0x0f000002 }; diff --git a/lib/init.c b/lib/init.c index beebd4f..18f3fb2 100644 --- a/lib/init.c +++ b/lib/init.c @@ -534,3 +534,9 @@ iscsi_set_initial_r2t(struct iscsi_context *iscsi, enum iscsi_initial_r2t initia return 0; } +int +iscsi_set_timeout(struct iscsi_context *iscsi, int timeout) +{ + iscsi->scsi_timeout = timeout; + return 0; +} diff --git a/lib/iscsi-command.c b/lib/iscsi-command.c index 0fdd143..94505d7 100644 --- a/lib/iscsi-command.c +++ b/lib/iscsi-command.c @@ -148,6 +148,45 @@ iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu, return 0; } +void +iscsi_timeout_scan(struct iscsi_context *iscsi) +{ + struct iscsi_pdu *pdu; + struct iscsi_pdu *next_pdu; + time_t t = time(NULL); + + for (pdu = iscsi->waitpdu; pdu; pdu = next_pdu) { + struct iscsi_scsi_cbdata *scsi_cbdata; + struct scsi_task *task; + + next_pdu = pdu->next; + + if (pdu->scsi_timeout == 0) { + /* no timeout for this pdu */ + continue; + } + if (t < pdu->scsi_timeout) { + /* not expired yet */ + continue; + } + if (pdu->outdata.data[0] != ISCSI_PDU_SCSI_REQUEST) { + continue; + } + + scsi_cbdata = &pdu->scsi_cbdata; + task = scsi_cbdata->task; + + SLIST_REMOVE(&iscsi->waitpdu, pdu); + pdu->callback(iscsi, SCSI_STATUS_TIMEOUT, + task, pdu->private_data); + iscsi_set_error(iscsi, "SCSI command timed out"); + + /* task is freed by the sync caller */ + task->status = SCSI_STATUS_TIMEOUT; + } +} + + /* Using 'struct iscsi_data *d' for data-out is optional * and will be converted into a one element data-out iovector. */ @@ -1662,3 +1701,4 @@ iscsi_scsi_cancel_all_tasks(struct iscsi_context *iscsi) iscsi_free_pdu(iscsi, pdu); } } + diff --git a/lib/libiscsi.def b/lib/libiscsi.def index b323122..55c5aed 100644 --- a/lib/libiscsi.def +++ b/lib/libiscsi.def @@ -63,6 +63,7 @@ iscsi_report_supported_opcodes_task iscsi_reconnect iscsi_set_noautoreconnect iscsi_set_reconnect_max_retries +iscsi_set_timeout iscsi_reportluns_sync iscsi_reportluns_task iscsi_scsi_cancel_all_tasks diff --git a/lib/libiscsi.syms b/lib/libiscsi.syms index d087caa..fd01090 100644 --- a/lib/libiscsi.syms +++ b/lib/libiscsi.syms @@ -61,6 +61,7 @@ iscsi_report_supported_opcodes_task iscsi_reconnect iscsi_set_noautoreconnect iscsi_set_reconnect_max_retries +iscsi_set_timeout iscsi_reportluns_sync iscsi_reportluns_task iscsi_scsi_cancel_all_tasks diff --git a/lib/socket.c b/lib/socket.c index 71e1021..a855f92 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -61,6 +61,7 @@ #include #include #include +#include #include "scsi-lowlevel.h" #include "iscsi.h" #include "iscsi-private.h" @@ -73,7 +74,13 @@ iscsi_add_to_outqueue(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { struct iscsi_pdu *current = iscsi->outqueue; struct iscsi_pdu *last = NULL; - + + if (iscsi->scsi_timeout > 0) { + pdu->scsi_timeout = time(NULL) + iscsi->scsi_timeout; + } else { + pdu->scsi_timeout = 0; + } + if (iscsi->outqueue == NULL) { iscsi->outqueue = pdu; pdu->next = NULL; diff --git a/lib/sync.c b/lib/sync.c index 334efff..3b2bb8c 100644 --- a/lib/sync.c +++ b/lib/sync.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "iscsi.h" #include "iscsi-private.h" #include "scsi-lowlevel.h" @@ -60,7 +61,7 @@ event_loop(struct iscsi_context *iscsi, struct iscsi_sync_state *state) return; } if (ret == 0) { - /* poll timedout, try again */ + iscsi_timeout_scan(iscsi); continue; } if (iscsi_service(iscsi, pfd.revents) < 0) { diff --git a/test-tool/iscsi-support.c b/test-tool/iscsi-support.c index 7b587b6..68ef4ee 100644 --- a/test-tool/iscsi-support.c +++ b/test-tool/iscsi-support.c @@ -1390,6 +1390,12 @@ testunitready(struct iscsi_context *iscsi, int lun) iscsi_get_error(iscsi)); return -1; } + if (task->status == SCSI_STATUS_TIMEOUT) { + logging(LOG_NORMAL, + "TESTUNITREADY timed out"); + scsi_free_scsi_task(task); + return -1; + } if (task->status != SCSI_STATUS_GOOD) { logging(LOG_NORMAL, "[FAILED] TESTUNITREADY command: failed with sense. %s", diff --git a/test-tool/iscsi-test-cu.c b/test-tool/iscsi-test-cu.c index 8096686..34bfe07 100644 --- a/test-tool/iscsi-test-cu.c +++ b/test-tool/iscsi-test-cu.c @@ -61,312 +61,298 @@ int (*real_iscsi_queue_pdu)(struct iscsi_context *iscsi, struct iscsi_pdu *pdu); * *****************************************************************/ static CU_TestInfo tests_get_lba_status[] = { - { (char *)"testGetLBAStatusSimple", test_get_lba_status_simple }, - { (char *)"testGetLBAStatusBeyondEol", test_get_lba_status_beyond_eol }, + { (char *)"GetLBAStatusSimple", test_get_lba_status_simple }, + { (char *)"GetLBAStatusBeyondEol", test_get_lba_status_beyond_eol }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_inquiry[] = { - { (char *)"testInquiryStandard", test_inquiry_standard }, - { (char *)"testInquiryAllocLength", test_inquiry_alloc_length}, - { (char *)"testInquiryEVPD", test_inquiry_evpd}, - { (char *)"testInquirySupportedVPD", test_inquiry_supported_vpd}, - { (char *)"testInquiryMandatoryVPDSBC", test_inquiry_mandatory_vpd_sbc}, + { (char *)"InquiryStandard", test_inquiry_standard }, + { (char *)"InquiryAllocLength", test_inquiry_alloc_length}, + { (char *)"InquiryEVPD", test_inquiry_evpd}, + { (char *)"InquirySupportedVPD", test_inquiry_supported_vpd}, + { (char *)"InquiryMandatoryVPDSBC", test_inquiry_mandatory_vpd_sbc}, CU_TEST_INFO_NULL }; static CU_TestInfo tests_mandatory[] = { - { (char *)"testMandatorySBC", test_mandatory_sbc }, + { (char *)"MandatorySBC", test_mandatory_sbc }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_nomedia[] = { - { (char *)"testNoMediaSBC", test_nomedia_sbc }, + { (char *)"NoMediaSBC", test_nomedia_sbc }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_orwrite[] = { - { (char *)"testOrWriteSimple", test_orwrite_simple }, - { (char *)"testOrWriteBeyondEol", test_orwrite_beyond_eol }, - { (char *)"testOrWriteZeroBlocks", test_orwrite_0blocks }, - { (char *)"testOrWriteProtect", test_orwrite_wrprotect }, - { (char *)"testOrWriteFlags", test_orwrite_flags }, - { (char *)"testOrWriteVerify", test_orwrite_verify }, + { (char *)"OrWriteSimple", test_orwrite_simple }, + { (char *)"OrWriteBeyondEol", test_orwrite_beyond_eol }, + { (char *)"OrWriteZeroBlocks", test_orwrite_0blocks }, + { (char *)"OrWriteProtect", test_orwrite_wrprotect }, + { (char *)"OrWriteFlags", test_orwrite_flags }, + { (char *)"OrWriteVerify", test_orwrite_verify }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_prefetch10[] = { - { (char *)"testPrefetch10Simple", test_prefetch10_simple }, - { (char *)"testPrefetch10BeyondEol", test_prefetch10_beyond_eol }, - { (char *)"testPrefetch10ZeroBlocks", test_prefetch10_0blocks }, - { (char *)"testPrefetch10Flags", test_prefetch10_flags }, + { (char *)"Prefetch10Simple", test_prefetch10_simple }, + { (char *)"Prefetch10BeyondEol", test_prefetch10_beyond_eol }, + { (char *)"Prefetch10ZeroBlocks", test_prefetch10_0blocks }, + { (char *)"Prefetch10Flags", test_prefetch10_flags }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_prefetch16[] = { - { (char *)"testPrefetch16Simple", test_prefetch16_simple }, - { (char *)"testPrefetch16BeyondEol", test_prefetch16_beyond_eol }, - { (char *)"testPrefetch16ZeroBlocks", test_prefetch16_0blocks }, - { (char *)"testPrefetch16Flags", test_prefetch16_flags }, + { (char *)"Prefetch16Simple", test_prefetch16_simple }, + { (char *)"Prefetch16BeyondEol", test_prefetch16_beyond_eol }, + { (char *)"Prefetch16ZeroBlocks", test_prefetch16_0blocks }, + { (char *)"Prefetch16Flags", test_prefetch16_flags }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_preventallow[] = { - { (char *)"testPreventAllowSimple", test_preventallow_simple }, - { (char *)"testPreventAllowEject", test_preventallow_eject }, - { (char *)"testPreventAllowITNexusLoss", test_preventallow_itnexus_loss }, - { (char *)"testPreventAllowLogout", test_preventallow_logout }, - { (char *)"testPreventAllowWarmReset", test_preventallow_warm_reset }, - { (char *)"testPreventAllowColdReset", test_preventallow_cold_reset }, - { (char *)"testPreventAllowLUNReset", test_preventallow_lun_reset }, - { (char *)"testPreventAllow2ITNexuses", test_preventallow_2_itnexuses }, + { (char *)"PreventAllowSimple", test_preventallow_simple }, + { (char *)"PreventAllowEject", test_preventallow_eject }, + { (char *)"PreventAllowITNexusLoss", test_preventallow_itnexus_loss }, + { (char *)"PreventAllowLogout", test_preventallow_logout }, + { (char *)"PreventAllowWarmReset", test_preventallow_warm_reset }, + { (char *)"PreventAllowColdReset", test_preventallow_cold_reset }, + { (char *)"PreventAllowLUNReset", test_preventallow_lun_reset }, + { (char *)"PreventAllow2ITNexuses", test_preventallow_2_itnexuses }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_prin_read_keys[] = { - { (char *)"testPrinReadKeysSimple", test_prin_read_keys_simple }, + { (char *)"PrinReadKeysSimple", test_prin_read_keys_simple }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_prout_register[] = { - { (char *)"testProutRegisterSimple", test_prout_register_simple }, + { (char *)"ProutRegisterSimple", test_prout_register_simple }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_prout_reserve[] = { - { (char *)"testProutReserveSimple", + { (char *)"ProutReserveSimple", test_prout_reserve_simple }, - { (char *)"testProutReserveAccessEA", + { (char *)"ProutReserveAccessEA", test_prout_reserve_access_ea }, - { (char *)"testProutReserveAccessWE", + { (char *)"ProutReserveAccessWE", test_prout_reserve_access_we }, - { (char *)"testProutReserveAccessEARO", + { (char *)"ProutReserveAccessEARO", test_prout_reserve_access_earo }, - { (char *)"testProutReserveAccessWERO", + { (char *)"ProutReserveAccessWERO", test_prout_reserve_access_wero }, - { (char *)"testProutReserveAccessEAAR", + { (char *)"ProutReserveAccessEAAR", test_prout_reserve_access_eaar }, - { (char *)"testProutReserveAccessWEAR", + { (char *)"ProutReserveAccessWEAR", test_prout_reserve_access_wear }, - { (char *)"testProutReserveOwnershipEA", + { (char *)"ProutReserveOwnershipEA", test_prout_reserve_ownership_ea }, - { (char *)"testProutReserveOwnershipWE", + { (char *)"ProutReserveOwnershipWE", test_prout_reserve_ownership_we }, - { (char *)"testProutReserveOwnershipEARO", + { (char *)"ProutReserveOwnershipEARO", test_prout_reserve_ownership_earo }, - { (char *)"testProutReserveOwnershipWERO", + { (char *)"ProutReserveOwnershipWERO", test_prout_reserve_ownership_wero }, - { (char *)"testProutReserveOwnershipEAAR", + { (char *)"ProutReserveOwnershipEAAR", test_prout_reserve_ownership_eaar }, - { (char *)"testProutReserveOwnershipWEAR", + { (char *)"ProutReserveOwnershipWEAR", test_prout_reserve_ownership_wear }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_prin_serviceaction_range[] = { - { (char *)"testPrinServiceactionRange", test_prin_serviceaction_range }, + { (char *)"PrinServiceactionRange", test_prin_serviceaction_range }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_read6[] = { - { (char *)"testRead6Simple", test_read6_simple }, - { (char *)"testRead6BeyondEol", test_read6_beyond_eol }, - { (char *)"testRead6ZeroBlocks", test_read6_0blocks }, + { (char *)"Read6Simple", test_read6_simple }, + { (char *)"Read6BeyondEol", test_read6_beyond_eol }, + { (char *)"Read6ZeroBlocks", test_read6_0blocks }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_read10[] = { - { (char *)"testRead10Simple", test_read10_simple }, - { (char *)"testRead10BeyondEol", test_read10_beyond_eol }, - { (char *)"testRead10ZeroBlocks", test_read10_0blocks }, - { (char *)"testRead10ReadProtect", test_read10_rdprotect }, - { (char *)"testRead10Flags", test_read10_flags }, + { (char *)"Read10Simple", test_read10_simple }, + { (char *)"Read10BeyondEol", test_read10_beyond_eol }, + { (char *)"Read10ZeroBlocks", test_read10_0blocks }, + { (char *)"Read10ReadProtect", test_read10_rdprotect }, + { (char *)"Read10Flags", test_read10_flags }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_read12[] = { - { (char *)"testRead12Simple", test_read12_simple }, - { (char *)"testRead12BeyondEol", test_read12_beyond_eol }, - { (char *)"testRead12ZeroBlocks", test_read12_0blocks }, - { (char *)"testRead12ReadProtect", test_read12_rdprotect }, - { (char *)"testRead12Flags", test_read12_flags }, + { (char *)"Read12Simple", test_read12_simple }, + { (char *)"Read12BeyondEol", test_read12_beyond_eol }, + { (char *)"Read12ZeroBlocks", test_read12_0blocks }, + { (char *)"Read12ReadProtect", test_read12_rdprotect }, + { (char *)"Read12Flags", test_read12_flags }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_read16[] = { - { (char *)"testRead16Simple", test_read16_simple }, - { (char *)"testRead16BeyondEol", test_read16_beyond_eol }, - { (char *)"testRead16ZeroBlocks", test_read16_0blocks }, - { (char *)"testRead16ReadProtect", test_read16_rdprotect }, - { (char *)"testRead16Flags", test_read16_flags }, + { (char *)"Read16Simple", test_read16_simple }, + { (char *)"Read16BeyondEol", test_read16_beyond_eol }, + { (char *)"Read16ZeroBlocks", test_read16_0blocks }, + { (char *)"Read16ReadProtect", test_read16_rdprotect }, + { (char *)"Read16Flags", test_read16_flags }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_readcapacity10[] = { - { (char *)"testReadCapacity10Simple", test_readcapacity10_simple }, + { (char *)"ReadCapacity10Simple", test_readcapacity10_simple }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_readcapacity16[] = { - { (char *)"testReadCapacity16Simple", test_readcapacity16_simple }, - { (char *)"testReadCapacity16Alloclen", test_readcapacity16_alloclen }, + { (char *)"ReadCapacity16Simple", test_readcapacity16_simple }, + { (char *)"ReadCapacity16Alloclen", test_readcapacity16_alloclen }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_readonly[] = { - { (char *)"testReadOnlySBC", test_readonly_sbc }, + { (char *)"ReadOnlySBC", test_readonly_sbc }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_reserve6[] = { - { (char *)"testReserve6Simple", test_reserve6_simple }, - { (char *)"testReserve6_2Initiators", test_reserve6_2initiators }, - { (char *)"testReserve6Logout", test_reserve6_logout }, - { (char *)"testReserve6ITNexusLoss", test_reserve6_itnexus_loss }, - { (char *)"testReserve6TargetColdReset", test_reserve6_target_cold_reset }, - { (char *)"testReserve6TargetWarmReset", test_reserve6_target_warm_reset }, - { (char *)"testReserve6LUNReset", test_reserve6_lun_reset }, + { (char *)"Reserve6Simple", test_reserve6_simple }, + { (char *)"Reserve6_2Initiators", test_reserve6_2initiators }, + { (char *)"Reserve6Logout", test_reserve6_logout }, + { (char *)"Reserve6ITNexusLoss", test_reserve6_itnexus_loss }, + { (char *)"Reserve6TargetColdReset", test_reserve6_target_cold_reset }, + { (char *)"Reserve6TargetWarmReset", test_reserve6_target_warm_reset }, + { (char *)"Reserve6LUNReset", test_reserve6_lun_reset }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_testunitready[] = { - { (char *)"testTurSimple", test_testunitready_simple }, + { (char *)"TurSimple", test_testunitready_simple }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_startstopunit[] = { - { (char *)"testStartStopUnitSimple", test_startstopunit_simple }, - { (char *)"testStartStopUnitPwrCnd", test_startstopunit_pwrcnd }, - { (char *)"testStartStopUnitNoLoej", test_startstopunit_noloej }, + { (char *)"StartStopUnitSimple", test_startstopunit_simple }, + { (char *)"StartStopUnitPwrCnd", test_startstopunit_pwrcnd }, + { (char *)"StartStopUnitNoLoej", test_startstopunit_noloej }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_unmap[] = { - { (char *)"testUnmapSimple", test_unmap_simple }, - { (char *)"testUnmapZeroBlocks", test_unmap_0blocks }, + { (char *)"UnmapSimple", test_unmap_simple }, + { (char *)"UnmapZeroBlocks", test_unmap_0blocks }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_verify10[] = { - { (char *)"testVerify10Simple", test_verify10_simple }, - { (char *)"testVerify10BeyondEol", test_verify10_beyond_eol }, - { (char *)"testVerify10ZeroBlocks", test_verify10_0blocks }, - { (char *)"testVerify10VerifyProtect", test_verify10_vrprotect }, - { (char *)"testVerify10Flags", test_verify10_flags }, - { (char *)"testVerify10mismatch", test_verify10_mismatch }, - { (char *)"testVerify10mismatch_no_cmp", test_verify10_mismatch_no_cmp }, + { (char *)"Verify10Simple", test_verify10_simple }, + { (char *)"Verify10BeyondEol", test_verify10_beyond_eol }, + { (char *)"Verify10ZeroBlocks", test_verify10_0blocks }, + { (char *)"Verify10VerifyProtect", test_verify10_vrprotect }, + { (char *)"Verify10Flags", test_verify10_flags }, + { (char *)"Verify10mismatch", test_verify10_mismatch }, + { (char *)"Verify10mismatch_no_cmp", test_verify10_mismatch_no_cmp }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_verify12[] = { - { (char *)"testVerify12Simple", test_verify12_simple }, - { (char *)"testVerify12BeyondEol", test_verify12_beyond_eol }, - { (char *)"testVerify12ZeroBlocks", test_verify12_0blocks }, - { (char *)"testVerify12VerifyProtect", test_verify12_vrprotect }, - { (char *)"testVerify12Flags", test_verify12_flags }, - { (char *)"testVerify12mismatch", test_verify12_mismatch }, - { (char *)"testVerify12mismatch_no_cmp", test_verify12_mismatch_no_cmp }, + { (char *)"Verify12Simple", test_verify12_simple }, + { (char *)"Verify12BeyondEol", test_verify12_beyond_eol }, + { (char *)"Verify12ZeroBlocks", test_verify12_0blocks }, + { (char *)"Verify12VerifyProtect", test_verify12_vrprotect }, + { (char *)"Verify12Flags", test_verify12_flags }, + { (char *)"Verify12mismatch", test_verify12_mismatch }, + { (char *)"Verify12mismatch_no_cmp", test_verify12_mismatch_no_cmp }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_verify16[] = { - { (char *)"testVerify16Simple", test_verify16_simple }, - { (char *)"testVerify16BeyondEol", test_verify16_beyond_eol }, - { (char *)"testVerify16ZeroBlocks", test_verify16_0blocks }, - { (char *)"testVerify16VerifyProtect", test_verify16_vrprotect }, - { (char *)"testVerify16Flags", test_verify16_flags }, - { (char *)"testVerify16mismatch", test_verify16_mismatch }, - { (char *)"testVerify16mismatch_no_cmp", test_verify16_mismatch_no_cmp }, + { (char *)"Verify16Simple", test_verify16_simple }, + { (char *)"Verify16BeyondEol", test_verify16_beyond_eol }, + { (char *)"Verify16ZeroBlocks", test_verify16_0blocks }, + { (char *)"Verify16VerifyProtect", test_verify16_vrprotect }, + { (char *)"Verify16Flags", test_verify16_flags }, + { (char *)"Verify16mismatch", test_verify16_mismatch }, + { (char *)"Verify16mismatch_no_cmp", test_verify16_mismatch_no_cmp }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_write10[] = { - { (char *)"testWrite10Simple", test_write10_simple }, - { (char *)"testWrite10BeyondEol", test_write10_beyond_eol }, - { (char *)"testWrite10ZeroBlocks", test_write10_0blocks }, - { (char *)"testWrite10WriteProtect", test_write10_wrprotect }, - { (char *)"testWrite10Flags", test_write10_flags }, + { (char *)"Write10Simple", test_write10_simple }, + { (char *)"Write10BeyondEol", test_write10_beyond_eol }, + { (char *)"Write10ZeroBlocks", test_write10_0blocks }, + { (char *)"Write10WriteProtect", test_write10_wrprotect }, + { (char *)"Write10Flags", test_write10_flags }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_write12[] = { - { (char *)"testWrite12Simple", test_write12_simple }, - { (char *)"testWrite12BeyondEol", test_write12_beyond_eol }, - { (char *)"testWrite12ZeroBlocks", test_write12_0blocks }, - { (char *)"testWrite12WriteProtect", test_write12_wrprotect }, - { (char *)"testWrite12Flags", test_write12_flags }, + { (char *)"Write12Simple", test_write12_simple }, + { (char *)"Write12BeyondEol", test_write12_beyond_eol }, + { (char *)"Write12ZeroBlocks", test_write12_0blocks }, + { (char *)"Write12WriteProtect", test_write12_wrprotect }, + { (char *)"Write12Flags", test_write12_flags }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_write16[] = { - { (char *)"testWrite16Simple", test_write16_simple }, - { (char *)"testWrite16BeyondEol", test_write16_beyond_eol }, - { (char *)"testWrite16ZeroBlocks", test_write16_0blocks }, - { (char *)"testWrite16WriteProtect", test_write16_wrprotect }, - { (char *)"testWrite16Flags", test_write16_flags }, + { (char *)"Write16Simple", test_write16_simple }, + { (char *)"Write16BeyondEol", test_write16_beyond_eol }, + { (char *)"Write16ZeroBlocks", test_write16_0blocks }, + { (char *)"Write16WriteProtect", test_write16_wrprotect }, + { (char *)"Write16Flags", test_write16_flags }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_writesame10[] = { - { (char *)"testWriteSame10Simple", test_writesame10_simple }, - { (char *)"testWriteSame10BeyondEol", test_writesame10_beyond_eol }, - { (char *)"testWriteSame10ZeroBlocks", test_writesame10_0blocks }, - { (char *)"testWriteSame10WriteProtect", test_writesame10_wrprotect }, - { (char *)"testWriteSame10Unmap", test_writesame10_unmap }, - { (char *)"testWriteSame10UnmapUnaligned", test_writesame10_unmap_unaligned }, - { (char *)"testWriteSame10UnmapUntilEnd", test_writesame10_unmap_until_end }, + { (char *)"WriteSame10Simple", test_writesame10_simple }, + { (char *)"WriteSame10BeyondEol", test_writesame10_beyond_eol }, + { (char *)"WriteSame10ZeroBlocks", test_writesame10_0blocks }, + { (char *)"WriteSame10WriteProtect", test_writesame10_wrprotect }, + { (char *)"WriteSame10Unmap", test_writesame10_unmap }, + { (char *)"WriteSame10UnmapUnaligned", test_writesame10_unmap_unaligned }, + { (char *)"WriteSame10UnmapUntilEnd", test_writesame10_unmap_until_end }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_writesame16[] = { - { (char *)"testWriteSame16Simple", test_writesame16_simple }, - { (char *)"testWriteSame16BeyondEol", test_writesame16_beyond_eol }, - { (char *)"testWriteSame16ZeroBlocks", test_writesame16_0blocks }, - { (char *)"testWriteSame16WriteProtect", test_writesame16_wrprotect }, - { (char *)"testWriteSame16Unmap", test_writesame16_unmap }, - { (char *)"testWriteSame16UnmapUnaligned", test_writesame16_unmap_unaligned }, - { (char *)"testWriteSame16UnmapUntilEnd", test_writesame16_unmap_until_end }, + { (char *)"WriteSame16Simple", test_writesame16_simple }, + { (char *)"WriteSame16BeyondEol", test_writesame16_beyond_eol }, + { (char *)"WriteSame16ZeroBlocks", test_writesame16_0blocks }, + { (char *)"WriteSame16WriteProtect", test_writesame16_wrprotect }, + { (char *)"WriteSame16Unmap", test_writesame16_unmap }, + { (char *)"WriteSame16UnmapUnaligned", test_writesame16_unmap_unaligned }, + { (char *)"WriteSame16UnmapUntilEnd", test_writesame16_unmap_until_end }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_writeverify10[] = { - { (char *)"testWriteVerify10Simple", test_writeverify10_simple }, - { (char *)"testWriteVerify10BeyondEol", test_writeverify10_beyond_eol }, - { (char *)"testWriteVerify10ZeroBlocks", test_writeverify10_0blocks }, - { (char *)"testWriteVerify10WriteProtect", test_writeverify10_wrprotect }, - { (char *)"testWriteVerify10Flags", test_writeverify10_flags }, + { (char *)"WriteVerify10Simple", test_writeverify10_simple }, + { (char *)"WriteVerify10BeyondEol", test_writeverify10_beyond_eol }, + { (char *)"WriteVerify10ZeroBlocks", test_writeverify10_0blocks }, + { (char *)"WriteVerify10WriteProtect", test_writeverify10_wrprotect }, + { (char *)"WriteVerify10Flags", test_writeverify10_flags }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_writeverify12[] = { - { (char *)"testWriteVerify12Simple", test_writeverify12_simple }, - { (char *)"testWriteVerify12BeyondEol", test_writeverify12_beyond_eol }, - { (char *)"testWriteVerify12ZeroBlocks", test_writeverify12_0blocks }, - { (char *)"testWriteVerify12WriteProtect", test_writeverify12_wrprotect }, - { (char *)"testWriteVerify12Flags", test_writeverify12_flags }, + { (char *)"WriteVerify12Simple", test_writeverify12_simple }, + { (char *)"WriteVerify12BeyondEol", test_writeverify12_beyond_eol }, + { (char *)"WriteVerify12ZeroBlocks", test_writeverify12_0blocks }, + { (char *)"WriteVerify12WriteProtect", test_writeverify12_wrprotect }, + { (char *)"WriteVerify12Flags", test_writeverify12_flags }, CU_TEST_INFO_NULL }; static CU_TestInfo tests_writeverify16[] = { - { (char *)"testWriteVerify16Simple", test_writeverify16_simple }, - { (char *)"testWriteVerify16BeyondEol", test_writeverify16_beyond_eol }, - { (char *)"testWriteVerify16ZeroBlocks", test_writeverify16_0blocks }, - { (char *)"testWriteVerify16WriteProtect", test_writeverify16_wrprotect }, - { (char *)"testWriteVerify16Flags", test_writeverify16_flags }, - CU_TEST_INFO_NULL -}; - -static CU_TestInfo tests_iscsiresiduals[] = { - { (char *)"testRead10Invalid", test_read10_invalid }, - { (char *)"testRead10Residuals", test_read10_residuals }, - { (char *)"testRead12Residuals", test_read12_residuals }, - { (char *)"testRead16Residuals", test_read16_residuals }, - { (char *)"testWrite10Residuals", test_write10_residuals }, - { (char *)"testWrite12Residuals", test_write12_residuals }, - { (char *)"testWrite16Residuals", test_write16_residuals }, - { (char *)"testWriteVerify10Residuals", test_writeverify10_residuals }, - { (char *)"testWriteVerify12Residuals", test_writeverify12_residuals }, - { (char *)"testWriteVerify16Residuals", test_writeverify16_residuals }, + { (char *)"WriteVerify16Simple", test_writeverify16_simple }, + { (char *)"WriteVerify16BeyondEol", test_writeverify16_beyond_eol }, + { (char *)"WriteVerify16ZeroBlocks", test_writeverify16_0blocks }, + { (char *)"WriteVerify16WriteProtect", test_writeverify16_wrprotect }, + { (char *)"WriteVerify16Flags", test_writeverify16_flags }, CU_TEST_INFO_NULL }; @@ -415,7 +401,7 @@ static CU_SuiteInfo scsi_suites[] = { tests_reserve6 }, { (char *)"StartStopUnit", test_setup, test_teardown, tests_startstopunit }, - { (char *)"TestUnitReady", test_setup, test_teardown, + { (char *)"UnitReady", test_setup, test_teardown, tests_testunitready }, { (char *)"Unmap", test_setup, test_teardown, tests_unmap }, @@ -444,10 +430,31 @@ static CU_SuiteInfo scsi_suites[] = { CU_SUITE_INFO_NULL }; +static CU_TestInfo tests_iscsi_cmdsn[] = { + { (char *)"iSCSICmdSnInvalid", test_iscsi_cmdsn_invalid }, + CU_TEST_INFO_NULL +}; + +static CU_TestInfo tests_iscsi_residuals[] = { + { (char *)"Read10Invalid", test_read10_invalid }, + { (char *)"Read10Residuals", test_read10_residuals }, + { (char *)"Read12Residuals", test_read12_residuals }, + { (char *)"Read16Residuals", test_read16_residuals }, + { (char *)"Write10Residuals", test_write10_residuals }, + { (char *)"Write12Residuals", test_write12_residuals }, + { (char *)"Write16Residuals", test_write16_residuals }, + { (char *)"WriteVerify10Residuals", test_writeverify10_residuals }, + { (char *)"WriteVerify12Residuals", test_writeverify12_residuals }, + { (char *)"WriteVerify16Residuals", test_writeverify16_residuals }, + CU_TEST_INFO_NULL +}; + /* iSCSI protocol tests */ static CU_SuiteInfo iscsi_suites[] = { + { (char *)"iSCSIcmdsn", test_setup, test_teardown, + tests_iscsi_cmdsn }, { (char *)"iSCSIResiduals", test_setup, test_teardown, - tests_iscsiresiduals }, + tests_iscsi_residuals }, CU_SUITE_INFO_NULL }; @@ -521,8 +528,10 @@ static CU_SuiteInfo all_suites[] = { tests_writeverify12 }, { (char *)"WriteVerify16", test_setup, test_teardown, tests_writeverify16 }, + { (char *)"iSCSIcmdsn", test_setup, test_teardown, + tests_iscsi_cmdsn }, { (char *)"iSCSIResiduals", test_setup, test_teardown, - tests_iscsiresiduals }, + tests_iscsi_residuals }, CU_SUITE_INFO_NULL }; diff --git a/test-tool/iscsi-test-cu.h b/test-tool/iscsi-test-cu.h index 1ef1960..dd5c5cd 100644 --- a/test-tool/iscsi-test-cu.h +++ b/test-tool/iscsi-test-cu.h @@ -49,6 +49,8 @@ void test_inquiry_evpd(void); void test_inquiry_supported_vpd(void); void test_inquiry_mandatory_vpd_sbc(void); +void test_iscsi_cmdsn_invalid(void); + void test_mandatory_sbc(void); void test_nomedia_sbc(void); diff --git a/test-tool/test_iscsi_cmdsn_invalid.c b/test-tool/test_iscsi_cmdsn_invalid.c new file mode 100644 index 0000000..faf5fbc --- /dev/null +++ b/test-tool/test_iscsi_cmdsn_invalid.c @@ -0,0 +1,69 @@ +/* + Copyright (C) 2013 by Ronnie Sahlberg + + 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 . +*/ + +#include +#include +#include + +#include "iscsi.h" +#include "iscsi-private.h" +#include "scsi-lowlevel.h" +#include "iscsi-test-cu.h" + +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 */ + *(uint32_t *)&pdu->outdata.data[24] = htonl(iscsi->maxcmdsn + 1); + break; + case 2: + /* change the cmdsn so it becomes too small */ + *(uint32_t *)&pdu->outdata.data[24] = 0; + break; + } + + change_cmdsn = 0; + return 0; +} + +void test_iscsi_cmdsn_invalid(void) +{ + 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, "Test that a CMDSN > MAXCMDSN is an error"); + logging(LOG_VERBOSE, "Send a TESTUNITREADY with CMDSN == MAXCMDSN+1"); + + iscsic->use_immediate_data = ISCSI_IMMEDIATE_DATA_NO; + iscsic->target_max_recv_data_segment_length = block_size; + local_iscsi_queue_pdu = my_iscsi_queue_pdu; + change_cmdsn = 1; + /* we dont want autoreconnect since some targets will drop the + * on this condition. + */ + iscsi_set_noautoreconnect(iscsic, 1); + iscsi_set_timeout(iscsic, 3); + + ret = testunitready(iscsic, tgt_lun); + CU_ASSERT_EQUAL(ret, -1); +}