diff --git a/include/iscsi-private.h b/include/iscsi-private.h index d1d8d5e..00f215c 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -87,6 +87,7 @@ struct iscsi_context { unsigned char isid[6]; uint32_t itt; uint32_t cmdsn; + uint32_t min_cmdsn_waiting; uint32_t expcmdsn; uint32_t maxcmdsn; uint32_t statsn; @@ -152,6 +153,7 @@ struct iscsi_context { void* smalloc_ptrs[SMALL_ALLOC_MAX_FREE]; int smalloc_free; size_t smalloc_size; + int cache_allocations; time_t next_reconnect; int scsi_timeout; diff --git a/include/iscsi.h b/include/iscsi.h index c8f41bb..7aa2a44 100644 --- a/include/iscsi.h +++ b/include/iscsi.h @@ -51,7 +51,7 @@ struct sockaddr; "[:]\"" -EXTERN void iscsi_set_cache_allocations(int ca); +EXTERN void iscsi_set_cache_allocations(struct iscsi_context *iscsi, int ca); /* * The following three functions are used to integrate libiscsi in an event diff --git a/lib/connect.c b/lib/connect.c index dec2a4b..2fecb6c 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -411,6 +411,7 @@ int iscsi_reconnect(struct iscsi_context *old_iscsi) iscsi->tcp_keepcnt = old_iscsi->tcp_keepcnt; iscsi->tcp_keepintvl = old_iscsi->tcp_keepintvl; iscsi->tcp_syncnt = old_iscsi->tcp_syncnt; + iscsi->cache_allocations = old_iscsi->cache_allocations; iscsi->reconnect_max_retries = old_iscsi->reconnect_max_retries; diff --git a/lib/init.c b/lib/init.c index 54dd1b1..5a867e1 100644 --- a/lib/init.c +++ b/lib/init.c @@ -33,15 +33,13 @@ #include "iscsi-private.h" #include "slist.h" -int cache_allocations = 1; - /** * Whether or not the internal memory allocator caches allocations. Disable * memory allocation caching to improve the accuracy of Valgrind reports. */ -void iscsi_set_cache_allocations(int ca) +void iscsi_set_cache_allocations(struct iscsi_context *iscsi, int ca) { - cache_allocations = ca; + iscsi->cache_allocations = ca; } void* iscsi_malloc(struct iscsi_context *iscsi, size_t size) { @@ -96,24 +94,15 @@ void iscsi_sfree(struct iscsi_context *iscsi, void* ptr) { if (ptr == NULL) { return; } - if (cache_allocations) { - if (iscsi->smalloc_free == SMALL_ALLOC_MAX_FREE) { - int i; - /* SMALL_ALLOC_MAX_FREE should be adjusted that this */ - /* happens rarely */ - ISCSI_LOG(iscsi, 6, "smalloc free == SMALLOC_MAX_FREE"); - /* remove oldest half of free pointers and copy - * upper half to lower half */ - iscsi->smalloc_free >>= 1; - for (i = 0; i < iscsi->smalloc_free; i++) { - iscsi_free(iscsi, iscsi->smalloc_ptrs[i]); - iscsi->smalloc_ptrs[i] = - iscsi->smalloc_ptrs[i + iscsi->smalloc_free]; - } - } - iscsi->smalloc_ptrs[iscsi->smalloc_free++] = ptr; - } else { + if (!iscsi->cache_allocations) { iscsi_free(iscsi, ptr); + } else if (iscsi->smalloc_free == SMALL_ALLOC_MAX_FREE) { + /* SMALL_ALLOC_MAX_FREE should be adjusted that this */ + /* happens rarely */ + ISCSI_LOG(iscsi, 6, "smalloc free == SMALLOC_MAX_FREE"); + iscsi_free(iscsi, ptr); + } else { + iscsi->smalloc_ptrs[iscsi->smalloc_free++] = ptr; } } @@ -122,6 +111,7 @@ iscsi_create_context(const char *initiator_name) { struct iscsi_context *iscsi; size_t required = ISCSI_RAW_HEADER_SIZE + ISCSI_DIGEST_SIZE; + char *ca; if (!initiator_name[0]) { return NULL; @@ -204,6 +194,11 @@ iscsi_create_context(const char *initiator_name) } ISCSI_LOG(iscsi,5,"small allocation size is %d byte", iscsi->smalloc_size); + ca = getenv("LIBISCSI_CACHE_ALLOCATIONS"); + if (!ca || atoi(ca) != 0) { + iscsi->cache_allocations = 1; + } + return iscsi; } diff --git a/lib/login.c b/lib/login.c index 9b813d7..81d1d2b 100644 --- a/lib/login.c +++ b/lib/login.c @@ -794,7 +794,7 @@ iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb, if (!iscsi->current_phase && !iscsi->secneg_phase) { iscsi->itt = (u_int32_t) rand(); iscsi->cmdsn = (u_int32_t) rand(); - iscsi->expcmdsn = iscsi->maxcmdsn = iscsi->cmdsn; + iscsi->expcmdsn = iscsi->maxcmdsn = iscsi->min_cmdsn_waiting = iscsi->cmdsn; } pdu = iscsi_allocate_pdu(iscsi, diff --git a/lib/nop.c b/lib/nop.c index 548e73e..f4fec90 100644 --- a/lib/nop.c +++ b/lib/nop.c @@ -21,6 +21,7 @@ #endif #include +#include #include "iscsi.h" #include "iscsi-private.h" @@ -143,7 +144,16 @@ iscsi_process_nop_out_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, "NOP-In received (pdu->itt %08x, pdu->ttt %08x, iscsi->maxcmdsn %08x, iscsi->expcmdsn %08x, iscsi->statsn %08x)", pdu->itt, 0xffffffff, iscsi->maxcmdsn, iscsi->expcmdsn, iscsi->statsn); - iscsi->nops_in_flight = 0; + if (iscsi->waitpdu->cmdsn == iscsi->min_cmdsn_waiting) { + ISCSI_LOG(iscsi, 2, "Oldest element in waitqueue is unchanged since last NOP-In (iscsi->min_cmdsn_waiting %08x)", + iscsi->min_cmdsn_waiting); + if (getenv("LIBISCSI_IGNORE_NOP_OUT_ON_STUCK_WAITPDU_QUEUE") == NULL) { + iscsi->nops_in_flight = 0; + } + } else { + iscsi->nops_in_flight = 0; + } + iscsi->min_cmdsn_waiting = iscsi->waitpdu->cmdsn; if (pdu->callback == NULL) { return 0; diff --git a/lib/socket.c b/lib/socket.c index 15095e3..da89c5a 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -879,17 +879,16 @@ iscsi_service(struct iscsi_context *iscsi, int revents) return 0; } - if (revents & POLLOUT && (iscsi->outqueue != NULL || iscsi->outqueue_current != NULL)) { - if (iscsi_write_to_socket(iscsi) != 0) { - return iscsi_service_reconnect_if_loggedin(iscsi); - } - } if (revents & POLLIN) { if (iscsi_read_from_socket(iscsi) != 0) { return iscsi_service_reconnect_if_loggedin(iscsi); } } - + if (revents & POLLOUT) { + if (iscsi_write_to_socket(iscsi) != 0) { + return iscsi_service_reconnect_if_loggedin(iscsi); + } + } return 0; } diff --git a/test-tool/iscsi-test-cu.c b/test-tool/iscsi-test-cu.c index 7aa90f1..ae236b2 100644 --- a/test-tool/iscsi-test-cu.c +++ b/test-tool/iscsi-test-cu.c @@ -971,11 +971,6 @@ main(int argc, char *argv[]) }; int i, c; int opt_idx = 0; - char *ca; - - ca = getenv("LIBISCSI_CACHE_ALLOCATIONS"); - if (ca && atoi(ca) == 0) - iscsi_set_cache_allocations(0); sd = malloc(sizeof(struct scsi_device)); memset(sd, '\0', sizeof(struct scsi_device));