From 0b6b12ba53f66a20e0d10352a09335a657f8f394 Mon Sep 17 00:00:00 2001 From: Sitsofe Wheeler Date: Mon, 9 Sep 2013 16:42:15 +0100 Subject: [PATCH 1/3] TESTS: Fix COMPAREANDWRITE tests to send write data Previously COMPAREANDWRITE was only sending verify instance data which can cause targets to generate COMMAND ABORTED/NOT ENOUGH UNSOLICITED DATA errors due to the buffer being obviously too small to contain verify AND write instance data. The buffer size check has been modified and compareandwrite tests updated to pass a larger buffer with interesting write instance data. --- lib/iscsi-command.c | 4 ++-- lib/scsi-lowlevel.c | 2 +- test-tool/0340_compareandwrite_simple.c | 16 ++++++++++++++-- test-tool/0341_compareandwrite_mismatch.c | 10 +++++++--- test-tool/0343_compareandwrite_beyondeol.c | 8 ++++---- 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/lib/iscsi-command.c b/lib/iscsi-command.c index 9591b11..f4d12d5 100644 --- a/lib/iscsi-command.c +++ b/lib/iscsi-command.c @@ -981,9 +981,9 @@ iscsi_compareandwrite_task(struct iscsi_context *iscsi, int lun, uint64_t lba, struct scsi_task *task; struct iscsi_data d; - if (datalen % blocksize != 0) { + if (datalen % (blocksize * 2) != 0) { iscsi_set_error(iscsi, "Datalen:%d is not a multiple of the " - "blocksize:%d.", datalen, blocksize); + "blocksize * 2:%d.", datalen, blocksize * 2); return NULL; } diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c index d766772..331fce5 100644 --- a/lib/scsi-lowlevel.c +++ b/lib/scsi-lowlevel.c @@ -1802,7 +1802,7 @@ scsi_cdb_compareandwrite(uint64_t lba, uint32_t xferlen, int blocksize, int wrpr scsi_set_uint32(&task->cdb[2], lba >> 32); scsi_set_uint32(&task->cdb[6], lba & 0xffffffff); - task->cdb[13] = xferlen/blocksize; + task->cdb[13] = xferlen/blocksize/2; task->cdb[14] |= (group_number & 0x1f); task->cdb_size = 16; diff --git a/test-tool/0340_compareandwrite_simple.c b/test-tool/0340_compareandwrite_simple.c index 535542b..3567205 100644 --- a/test-tool/0340_compareandwrite_simple.c +++ b/test-tool/0340_compareandwrite_simple.c @@ -21,6 +21,14 @@ #include "scsi-lowlevel.h" #include "iscsi-test.h" +static void bitwise_invert(unsigned char data[], int len) { + int j; + + for (j = 0; j < len; j++) { + data[j] = ~data[j]; + } +} + int T0340_compareandwrite_simple(const char *initiator, const char *url) { struct iscsi_context *iscsi; @@ -80,9 +88,11 @@ int T0340_compareandwrite_simple(const char *initiator, const char *url) goto finished; } memcpy(data, task->datain.data, i * block_size); + memcpy(data + (i * block_size), task->datain.data, i * block_size); + bitwise_invert(data + (i * block_size), i * block_size); scsi_free_scsi_task(task); - task = iscsi_compareandwrite_sync(iscsi, lun, 0, data, i * block_size, block_size, 0, 0, 0, 0, 0); + task = iscsi_compareandwrite_sync(iscsi, lun, 0, data, i * 2 * block_size, block_size, 0, 0, 0, 0, 0); if (task == NULL) { printf("[FAILED]\n"); printf("Failed to send COMPAREANDWRITE command: %s\n", iscsi_get_error(iscsi)); @@ -136,9 +146,11 @@ int T0340_compareandwrite_simple(const char *initiator, const char *url) goto finished; } memcpy(data, task->datain.data, i * block_size); + memcpy(data + (i * block_size), task->datain.data, i * block_size); + bitwise_invert(data + (i * block_size), i * block_size); scsi_free_scsi_task(task); - task = iscsi_compareandwrite_sync(iscsi, lun, num_blocks + 1 - i, data, i * block_size, block_size, 0, 0, 0, 0, 0); + task = iscsi_compareandwrite_sync(iscsi, lun, num_blocks + 1 - i, data, i * 2 * block_size, block_size, 0, 0, 0, 0, 0); if (task == NULL) { printf("[FAILED]\n"); printf("Failed to send COMPAREANDWRITE command: %s\n", iscsi_get_error(iscsi)); diff --git a/test-tool/0341_compareandwrite_mismatch.c b/test-tool/0341_compareandwrite_mismatch.c index ca5adc0..645daa8 100644 --- a/test-tool/0341_compareandwrite_mismatch.c +++ b/test-tool/0341_compareandwrite_mismatch.c @@ -58,7 +58,7 @@ int T0341_compareandwrite_mismatch(const char *initiator, const char *url) /* write the first 1 - 255 blocks at the start of the LUN */ printf("Compare and write first 1-255 blocks (data is not matching) ... "); for (i = 1; i < 256; i++) { - task = iscsi_read16_sync(iscsi, lun, 0, i * block_size, block_size, 0, 0, 0, 0, 0); + task = iscsi_read16_sync(iscsi, lun, 0, i * 2 * block_size, block_size, 0, 0, 0, 0, 0); if (task == NULL) { printf("[FAILED]\n"); printf("Failed to send READ16 command: %s\n", iscsi_get_error(iscsi)); @@ -85,8 +85,10 @@ int T0341_compareandwrite_mismatch(const char *initiator, const char *url) /* flip some bits */ data[ (i - 1) * block_size] ^= 0xa5; + /* set the write part of the data-out buffer to 1s */ + memset(data + (i * block_size), 0xff, (i * block_size)); - task = iscsi_compareandwrite_sync(iscsi, lun, 0, data, i * block_size, block_size, 0, 0, 0, 0, 0); + task = iscsi_compareandwrite_sync(iscsi, lun, 0, data, i * 2 * block_size, block_size, 0, 0, 0, 0, 0); if (task == NULL) { printf("[FAILED]\n"); printf("Failed to send COMPAREANDWRITE command: %s\n", iscsi_get_error(iscsi)); @@ -153,8 +155,10 @@ int T0341_compareandwrite_mismatch(const char *initiator, const char *url) /* flip some bits */ data[ (i - 1) * block_size] ^= 0xa5; + /* set the write part of the data-out buffer to 1s */ + memset(data + (i * block_size), 0xff, (i * block_size)); - task = iscsi_compareandwrite_sync(iscsi, lun, num_blocks + 1 - i, data, i * block_size, block_size, 0, 0, 0, 0, 0); + task = iscsi_compareandwrite_sync(iscsi, lun, num_blocks + 1 - i, data, i * 2 * block_size, block_size, 0, 0, 0, 0, 0); if (task == NULL) { printf("[FAILED]\n"); printf("Failed to send COMPAREANDWRITE command: %s\n", iscsi_get_error(iscsi)); diff --git a/test-tool/0343_compareandwrite_beyondeol.c b/test-tool/0343_compareandwrite_beyondeol.c index 9451991..b416a1e 100644 --- a/test-tool/0343_compareandwrite_beyondeol.c +++ b/test-tool/0343_compareandwrite_beyondeol.c @@ -57,7 +57,7 @@ int T0343_compareandwrite_beyondeol(const char *initiator, const char *url) /* read 1 - 255 blocks beyond the end of the device */ printf("Writing 1-255 blocks with one block beyond end-of-device ... "); for (i = 1; i <= 255; i++) { - task = iscsi_compareandwrite_sync(iscsi, lun, num_blocks + 2 - i, data, i * block_size, block_size, 0, 0, 0, 0, 0); + task = iscsi_compareandwrite_sync(iscsi, lun, num_blocks + 2 - i, data, i * 2 * block_size, block_size, 0, 0, 0, 0, 0); if (task == NULL) { printf("[FAILED]\n"); printf("Failed to send COMPAREANDWRITE command: %s\n", iscsi_get_error(iscsi)); @@ -97,7 +97,7 @@ int T0343_compareandwrite_beyondeol(const char *initiator, const char *url) /* read 1 - 255 blocks at lba 2^63 */ printf("Writing 1-255 blocks at LBA 2^63 ... "); for (i = 1; i < 256; i++) { - task = iscsi_compareandwrite_sync(iscsi, lun, 0x8000000000000000, data, i * block_size, block_size, 0, 0, 0, 0, 0); + task = iscsi_compareandwrite_sync(iscsi, lun, 0x8000000000000000, data, i * 2 * block_size, block_size, 0, 0, 0, 0, 0); if (task == NULL) { printf("[FAILED]\n"); printf("Failed to send COMPAREANDWRITE command: %s\n", iscsi_get_error(iscsi)); @@ -128,7 +128,7 @@ int T0343_compareandwrite_beyondeol(const char *initiator, const char *url) /* read 1 - 255 blocks at lba -1 */ printf("Writing 1-255 blocks at LBA -1 ... "); for (i = 1; i < 256; i++) { - task = iscsi_compareandwrite_sync(iscsi, lun, 0xffffffffffffffff, data, i * block_size, block_size, 0, 0, 0, 0, 0); + task = iscsi_compareandwrite_sync(iscsi, lun, 0xffffffffffffffff, data, i * 2 * block_size, block_size, 0, 0, 0, 0, 0); if (task == NULL) { printf("[FAILED]\n"); printf("Failed to send COMPAREANDWRITE command: %s\n", iscsi_get_error(iscsi)); @@ -159,7 +159,7 @@ int T0343_compareandwrite_beyondeol(const char *initiator, const char *url) /* read 2-255 blocks, all but one block beyond the eol */ printf("Writing 1-255 blocks beyond eol starting at last block ... "); for (i = 2; i < 256; i++) { - task = iscsi_compareandwrite_sync(iscsi, lun, num_blocks, data, i * block_size, block_size, 0, 0, 0, 0, 0); + task = iscsi_compareandwrite_sync(iscsi, lun, num_blocks, data, i * 2 * block_size, block_size, 0, 0, 0, 0, 0); if (task == NULL) { printf("[FAILED]\n"); printf("Failed to send COMPAREANDWRITE command: %s\n", iscsi_get_error(iscsi)); From 7692027d6c11c58948ec3c493abea808af00fdd0 Mon Sep 17 00:00:00 2001 From: Sitsofe Wheeler Date: Sat, 7 Sep 2013 00:17:48 +0100 Subject: [PATCH 2/3] Fix compilation issues under clang clang defaults to c99 so remove inline statements (http://clang.llvm.org/compatibility.html#inline ) on functions shared across different translation units. clang's linker doesn't like major numbers over 255 so change how SOREL is generated in Makefile.am. --- Makefile.am | 7 +++++-- include/iscsi-private.h | 14 +++++++------- include/scsi-lowlevel.h | 8 ++++---- lib/init.c | 14 +++++++------- lib/scsi-lowlevel.c | 12 ++++++------ 5 files changed, 29 insertions(+), 26 deletions(-) diff --git a/Makefile.am b/Makefile.am index 6dfcf96..18a3f63 100644 --- a/Makefile.am +++ b/Makefile.am @@ -43,9 +43,12 @@ lib_libiscsi_la_SOURCES += lib/md5.c endif SONAME=3 -SOREL=$(shell printf "%d%02d%02d" $(subst ., ,$(VERSION))) +SOMAJOR = $(firstword $(version_split)) +SOMINOR = $(word 2, $(version_split)) +SOREVISION = $(word 3, $(version_split)) +SOREL = $(shell echo $(SOMINOR) + $(SOREVISION)) lib_libiscsi_la_LDFLAGS = \ - -version-info $(SONAME):$(SOREL):0 -bindir $(bindir) -no-undefined \ + -version-info $(SONAME):$(SOMAJOR):$(SOREL) -bindir $(bindir) -no-undefined \ -export-symbols $(srcdir)/lib/libiscsi.syms # libiscsi utilities diff --git a/include/iscsi-private.h b/include/iscsi-private.h index 25dbb7b..be85dbc 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -305,13 +305,13 @@ void iscsi_set_error(struct iscsi_context *iscsi, const char *error_string, struct scsi_iovector *iscsi_get_scsi_task_iovector_in(struct iscsi_context *iscsi, struct iscsi_in_pdu *in); struct scsi_iovector *iscsi_get_scsi_task_iovector_out(struct iscsi_context *iscsi, struct iscsi_pdu *pdu); -inline void* iscsi_malloc(struct iscsi_context *iscsi, size_t size); -inline void* iscsi_zmalloc(struct iscsi_context *iscsi, size_t size); -inline void* iscsi_realloc(struct iscsi_context *iscsi, void* ptr, size_t size); -inline void iscsi_free(struct iscsi_context *iscsi, void* ptr); -inline char* iscsi_strdup(struct iscsi_context *iscsi, const char* str); -inline void* iscsi_szmalloc(struct iscsi_context *iscsi, size_t size); -inline void iscsi_sfree(struct iscsi_context *iscsi, void* ptr); +void* iscsi_malloc(struct iscsi_context *iscsi, size_t size); +void* iscsi_zmalloc(struct iscsi_context *iscsi, size_t size); +void* iscsi_realloc(struct iscsi_context *iscsi, void* ptr, size_t size); +void iscsi_free(struct iscsi_context *iscsi, void* ptr); +char* iscsi_strdup(struct iscsi_context *iscsi, const char* str); +void* iscsi_szmalloc(struct iscsi_context *iscsi, size_t size); +void iscsi_sfree(struct iscsi_context *iscsi, void* ptr); unsigned long crc32c(char *buf, int len); diff --git a/include/scsi-lowlevel.h b/include/scsi-lowlevel.h index 90841b1..71df5f1 100644 --- a/include/scsi-lowlevel.h +++ b/include/scsi-lowlevel.h @@ -1074,10 +1074,10 @@ EXTERN struct scsi_task *scsi_cdb_writeverify16(uint64_t lba, uint32_t xferlen, void *scsi_malloc(struct scsi_task *task, size_t size); -inline uint32_t scsi_get_uint32(const unsigned char *c); -inline uint16_t scsi_get_uint16(const unsigned char *c); -inline void scsi_set_uint32(unsigned char *c, uint32_t val); -inline void scsi_set_uint16(unsigned char *c, uint16_t val); +uint32_t scsi_get_uint32(const unsigned char *c); +uint16_t scsi_get_uint16(const unsigned char *c); +void scsi_set_uint32(unsigned char *c, uint32_t val); +void scsi_set_uint16(unsigned char *c, uint16_t val); #ifdef __cplusplus } diff --git a/lib/init.c b/lib/init.c index 14a865f..048f59a 100644 --- a/lib/init.c +++ b/lib/init.c @@ -33,13 +33,13 @@ #include "iscsi-private.h" #include "slist.h" -inline void* iscsi_malloc(struct iscsi_context *iscsi, size_t size) { +void* iscsi_malloc(struct iscsi_context *iscsi, size_t size) { void * ptr = malloc(size); if (ptr != NULL) iscsi->mallocs++; return ptr; } -inline void* iscsi_zmalloc(struct iscsi_context *iscsi, size_t size) { +void* iscsi_zmalloc(struct iscsi_context *iscsi, size_t size) { void * ptr = malloc(size); if (ptr != NULL) { memset(ptr,0x00,size); @@ -48,7 +48,7 @@ inline void* iscsi_zmalloc(struct iscsi_context *iscsi, size_t size) { return ptr; } -inline void* iscsi_realloc(struct iscsi_context *iscsi, void* ptr, size_t size) { +void* iscsi_realloc(struct iscsi_context *iscsi, void* ptr, size_t size) { void * _ptr = realloc(ptr, size); if (_ptr != NULL) { iscsi->reallocs++; @@ -56,19 +56,19 @@ inline void* iscsi_realloc(struct iscsi_context *iscsi, void* ptr, size_t size) return _ptr; } -inline void iscsi_free(struct iscsi_context *iscsi, void* ptr) { +void iscsi_free(struct iscsi_context *iscsi, void* ptr) { if (ptr == NULL) return; free(ptr); iscsi->frees++; } -inline char* iscsi_strdup(struct iscsi_context *iscsi, const char* str) { +char* iscsi_strdup(struct iscsi_context *iscsi, const char* str) { char *str2 = strdup(str); if (str2 != NULL) iscsi->mallocs++; return str2; } -inline void* iscsi_szmalloc(struct iscsi_context *iscsi, size_t size) { +void* iscsi_szmalloc(struct iscsi_context *iscsi, size_t size) { void *ptr; if (size > iscsi->smalloc_size) return NULL; if (iscsi->smalloc_free > 0) { @@ -81,7 +81,7 @@ inline void* iscsi_szmalloc(struct iscsi_context *iscsi, size_t size) { return ptr; } -inline void iscsi_sfree(struct iscsi_context *iscsi, void* ptr) { +void iscsi_sfree(struct iscsi_context *iscsi, void* ptr) { if (ptr == NULL) return; if (iscsi->smalloc_free == SMALL_ALLOC_MAX_FREE) { /* SMALL_ALLOC_MAX_FREE should be adjusted that this happens rarely */ diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c index d766772..f8fdbde 100644 --- a/lib/scsi-lowlevel.c +++ b/lib/scsi-lowlevel.c @@ -235,7 +235,7 @@ scsi_pr_type_str(enum scsi_persistent_out_type pr_type) return value_string_find(pr_type_strings, pr_type); } -inline uint64_t +uint64_t scsi_get_uint64(const unsigned char *c) { uint64_t val; @@ -248,7 +248,7 @@ scsi_get_uint64(const unsigned char *c) return val; } -inline uint32_t +uint32_t scsi_get_uint32(const unsigned char *c) { uint32_t val; @@ -259,7 +259,7 @@ scsi_get_uint32(const unsigned char *c) return val; } -inline uint16_t +uint16_t scsi_get_uint16(const unsigned char *c) { uint16_t val; @@ -314,7 +314,7 @@ task_get_uint8(struct scsi_task *task, int offset) } } -inline void +void scsi_set_uint64(unsigned char *c, uint64_t v) { uint32_t val; @@ -327,7 +327,7 @@ scsi_set_uint64(unsigned char *c, uint64_t v) scsi_set_uint32(c, val); } -inline void +void scsi_set_uint32(unsigned char *c, uint32_t val) { c[0] = val >> 24; @@ -336,7 +336,7 @@ scsi_set_uint32(unsigned char *c, uint32_t val) c[3] = val; } -inline void +void scsi_set_uint16(unsigned char *c, uint16_t val) { c[0] = val >> 8; From 2fda87160cbca82053de57c6d263e650975457d8 Mon Sep 17 00:00:00 2001 From: Sitsofe Wheeler Date: Sat, 7 Sep 2013 00:17:48 +0100 Subject: [PATCH 3/3] Fix compilation on OS X OS X doesn't implement SOL_TCP so workaround this the same way as on FreeBSD/Solaris. --- README | 1 + lib/socket.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README b/README index 183248e..eb8adde 100644 --- a/README +++ b/README @@ -159,6 +159,7 @@ Libiscsi has been tested on: * Windows (Win7-VisualStudio10) * OpenSolaris * Solaris 11 : Use "gmake" to build. +* OS X RELEASE TARBALLS ================ diff --git a/lib/socket.c b/lib/socket.c index 6fbac80..468af32 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -129,7 +129,7 @@ int set_tcp_sockopt(int sockfd, int optname, int value) { int level; - #if defined(__FreeBSD__) || defined(__sun) + #if defined(__FreeBSD__) || defined(__sun) || (defined(__APPLE__) && defined(__MACH__)) struct protoent *buf; if ((buf = getprotobyname("tcp")) != NULL)