Merge pull request #67 from plieven/small_allocations
MEMORY introduce a small allocation pool
This commit is contained in:
@@ -39,6 +39,7 @@ extern "C" {
|
|||||||
#define ISCSI_HEADER_SIZE (ISCSI_RAW_HEADER_SIZE \
|
#define ISCSI_HEADER_SIZE (ISCSI_RAW_HEADER_SIZE \
|
||||||
+ (iscsi->header_digest == ISCSI_HEADER_DIGEST_NONE?0:ISCSI_DIGEST_SIZE))
|
+ (iscsi->header_digest == ISCSI_HEADER_DIGEST_NONE?0:ISCSI_DIGEST_SIZE))
|
||||||
|
|
||||||
|
#define SMALL_ALLOC_MAX_FREE (128) /* must be power of 2 */
|
||||||
|
|
||||||
struct iscsi_in_pdu {
|
struct iscsi_in_pdu {
|
||||||
struct iscsi_in_pdu *next;
|
struct iscsi_in_pdu *next;
|
||||||
@@ -131,6 +132,10 @@ struct iscsi_context {
|
|||||||
int mallocs;
|
int mallocs;
|
||||||
int reallocs;
|
int reallocs;
|
||||||
int frees;
|
int frees;
|
||||||
|
int smallocs;
|
||||||
|
void* smalloc_ptrs[SMALL_ALLOC_MAX_FREE];
|
||||||
|
int smalloc_free;
|
||||||
|
size_t smalloc_size;
|
||||||
|
|
||||||
time_t last_reconnect;
|
time_t last_reconnect;
|
||||||
int scsi_timeout;
|
int scsi_timeout;
|
||||||
@@ -301,6 +306,8 @@ 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_realloc(struct iscsi_context *iscsi, void* ptr, size_t size);
|
||||||
inline void iscsi_free(struct iscsi_context *iscsi, void* ptr);
|
inline void iscsi_free(struct iscsi_context *iscsi, void* ptr);
|
||||||
inline char* iscsi_strdup(struct iscsi_context *iscsi, const char* str);
|
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);
|
||||||
|
|
||||||
unsigned long crc32c(char *buf, int len);
|
unsigned long crc32c(char *buf, int len);
|
||||||
|
|
||||||
|
|||||||
50
lib/init.c
50
lib/init.c
@@ -33,7 +33,6 @@
|
|||||||
#include "iscsi-private.h"
|
#include "iscsi-private.h"
|
||||||
#include "slist.h"
|
#include "slist.h"
|
||||||
|
|
||||||
|
|
||||||
inline void* iscsi_malloc(struct iscsi_context *iscsi, size_t size) {
|
inline void* iscsi_malloc(struct iscsi_context *iscsi, size_t size) {
|
||||||
void * ptr = malloc(size);
|
void * ptr = malloc(size);
|
||||||
if (ptr != NULL) iscsi->mallocs++;
|
if (ptr != NULL) iscsi->mallocs++;
|
||||||
@@ -69,6 +68,36 @@ inline char* iscsi_strdup(struct iscsi_context *iscsi, const char* str) {
|
|||||||
return str2;
|
return str2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void* iscsi_szmalloc(struct iscsi_context *iscsi, size_t size) {
|
||||||
|
void *ptr;
|
||||||
|
if (size > iscsi->smalloc_size) return NULL;
|
||||||
|
if (iscsi->smalloc_free > 0) {
|
||||||
|
ptr = iscsi->smalloc_ptrs[--iscsi->smalloc_free];
|
||||||
|
memset(ptr, 0, iscsi->smalloc_size);
|
||||||
|
iscsi->smallocs++;
|
||||||
|
} else {
|
||||||
|
ptr = iscsi_zmalloc(iscsi, iscsi->smalloc_size);
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline 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 */
|
||||||
|
ISCSI_LOG(iscsi,6,"smalloc free == SMALLOC_MAX_FREE");
|
||||||
|
int i;
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
struct iscsi_context *
|
struct iscsi_context *
|
||||||
iscsi_create_context(const char *initiator_name)
|
iscsi_create_context(const char *initiator_name)
|
||||||
{
|
{
|
||||||
@@ -144,6 +173,16 @@ iscsi_create_context(const char *initiator_name)
|
|||||||
iscsi_set_bind_interfaces(iscsi,getenv("LIBISCSI_BIND_INTERFACES"));
|
iscsi_set_bind_interfaces(iscsi,getenv("LIBISCSI_BIND_INTERFACES"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* iscsi->smalloc_size is the size for small allocations. this should be
|
||||||
|
max(ISCSI_HEADER_SIZE, sizeof(struct iscsi_pdu), sizeof(struct iscsi_in_pdu))
|
||||||
|
rounded up to the next power of 2. */
|
||||||
|
iscsi->smalloc_size = 1;
|
||||||
|
size_t required = ISCSI_RAW_HEADER_SIZE + ISCSI_DIGEST_SIZE;
|
||||||
|
if (sizeof(struct iscsi_pdu) > required) required = sizeof(struct iscsi_pdu);
|
||||||
|
if (sizeof(struct iscsi_in_pdu) > required) required = sizeof(struct iscsi_in_pdu);
|
||||||
|
while (iscsi->smalloc_size < required) iscsi->smalloc_size <<= 1;
|
||||||
|
ISCSI_LOG(iscsi,5,"small allocation size is %d byte", iscsi->smalloc_size);
|
||||||
|
|
||||||
return iscsi;
|
return iscsi;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,6 +275,7 @@ int
|
|||||||
iscsi_destroy_context(struct iscsi_context *iscsi)
|
iscsi_destroy_context(struct iscsi_context *iscsi)
|
||||||
{
|
{
|
||||||
struct iscsi_pdu *pdu;
|
struct iscsi_pdu *pdu;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (iscsi == NULL) {
|
if (iscsi == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -283,10 +323,14 @@ iscsi_destroy_context(struct iscsi_context *iscsi)
|
|||||||
|
|
||||||
iscsi->connect_data = NULL;
|
iscsi->connect_data = NULL;
|
||||||
|
|
||||||
|
for (i=0;i<iscsi->smalloc_free;i++) {
|
||||||
|
iscsi_free(iscsi, iscsi->smalloc_ptrs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
if (iscsi->mallocs != iscsi->frees) {
|
if (iscsi->mallocs != iscsi->frees) {
|
||||||
ISCSI_LOG(iscsi,1,"%d memory blocks lost at iscsi_destroy_context() after %d malloc(s), %d realloc(s) and %d free(s)",iscsi->mallocs-iscsi->frees,iscsi->mallocs,iscsi->reallocs,iscsi->frees);
|
ISCSI_LOG(iscsi,1,"%d memory blocks lost at iscsi_destroy_context() after %d malloc(s), %d realloc(s), %d free(s) and %d reused small allocations",iscsi->mallocs-iscsi->frees,iscsi->mallocs,iscsi->reallocs,iscsi->frees,iscsi->smallocs);
|
||||||
} else {
|
} else {
|
||||||
ISCSI_LOG(iscsi,5,"memory is clean at iscsi_destroy_context() after %d mallocs, %d realloc(s) and %d frees",iscsi->mallocs,iscsi->reallocs,iscsi->frees);
|
ISCSI_LOG(iscsi,5,"memory is clean at iscsi_destroy_context() after %d mallocs, %d realloc(s), %d free(s) and %d reused small allocations",iscsi->mallocs,iscsi->reallocs,iscsi->frees,iscsi->smallocs);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(iscsi, 0, sizeof(struct iscsi_context));
|
memset(iscsi, 0, sizeof(struct iscsi_context));
|
||||||
|
|||||||
29
lib/pdu.c
29
lib/pdu.c
@@ -84,15 +84,14 @@ iscsi_allocate_pdu_with_itt_flags(struct iscsi_context *iscsi, enum iscsi_opcode
|
|||||||
{
|
{
|
||||||
struct iscsi_pdu *pdu;
|
struct iscsi_pdu *pdu;
|
||||||
|
|
||||||
pdu = iscsi_zmalloc(iscsi, sizeof(struct iscsi_pdu));
|
pdu = iscsi_szmalloc(iscsi, sizeof(struct iscsi_pdu));
|
||||||
if (pdu == NULL) {
|
if (pdu == NULL) {
|
||||||
iscsi_set_error(iscsi, "failed to allocate pdu");
|
iscsi_set_error(iscsi, "failed to allocate pdu");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pdu->outdata.size = ISCSI_HEADER_SIZE;
|
pdu->outdata.size = ISCSI_HEADER_SIZE;
|
||||||
pdu->outdata.data = iscsi_malloc(iscsi, pdu->outdata.size);
|
pdu->outdata.data = iscsi_szmalloc(iscsi, pdu->outdata.size);
|
||||||
memset(pdu->outdata.data, 0, ISCSI_HEADER_SIZE);
|
|
||||||
|
|
||||||
if (pdu->outdata.data == NULL) {
|
if (pdu->outdata.data == NULL) {
|
||||||
iscsi_set_error(iscsi, "failed to allocate pdu header");
|
iscsi_set_error(iscsi, "failed to allocate pdu header");
|
||||||
@@ -134,13 +133,21 @@ iscsi_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
iscsi_free(iscsi, pdu->outdata.data);
|
if (pdu->outdata.size <= iscsi->smalloc_size) {
|
||||||
|
iscsi_sfree(iscsi, pdu->outdata.data);
|
||||||
|
} else {
|
||||||
|
iscsi_free(iscsi, pdu->outdata.data);
|
||||||
|
}
|
||||||
pdu->outdata.data = NULL;
|
pdu->outdata.data = NULL;
|
||||||
|
|
||||||
iscsi_free(iscsi, pdu->indata.data);
|
if (pdu->indata.size <= iscsi->smalloc_size) {
|
||||||
|
iscsi_sfree(iscsi, pdu->indata.data);
|
||||||
|
} else {
|
||||||
|
iscsi_free(iscsi, pdu->indata.data);
|
||||||
|
}
|
||||||
pdu->indata.data = NULL;
|
pdu->indata.data = NULL;
|
||||||
|
|
||||||
iscsi_free(iscsi, pdu);
|
iscsi_sfree(iscsi, pdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -164,9 +171,15 @@ iscsi_add_data(struct iscsi_context *iscsi, struct iscsi_data *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data->size == 0) {
|
if (data->size == 0) {
|
||||||
data->data = iscsi_malloc(iscsi, aligned);
|
if (aligned <= iscsi->smalloc_size) {
|
||||||
|
data->data = iscsi_szmalloc(iscsi, aligned);
|
||||||
|
} else {
|
||||||
|
data->data = iscsi_malloc(iscsi, aligned);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
data->data = iscsi_realloc(iscsi, data->data, aligned);
|
if (aligned > iscsi->smalloc_size) {
|
||||||
|
data->data = iscsi_realloc(iscsi, data->data, aligned);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (data->data == NULL) {
|
if (data->data == NULL) {
|
||||||
iscsi_set_error(iscsi, "failed to allocate buffer for %d "
|
iscsi_set_error(iscsi, "failed to allocate buffer for %d "
|
||||||
|
|||||||
@@ -492,7 +492,7 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
|
|||||||
ssize_t data_size, count;
|
ssize_t data_size, count;
|
||||||
|
|
||||||
if (iscsi->incoming == NULL) {
|
if (iscsi->incoming == NULL) {
|
||||||
iscsi->incoming = iscsi_zmalloc(iscsi, sizeof(struct iscsi_in_pdu));
|
iscsi->incoming = iscsi_szmalloc(iscsi, sizeof(struct iscsi_in_pdu));
|
||||||
if (iscsi->incoming == NULL) {
|
if (iscsi->incoming == NULL) {
|
||||||
iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu");
|
iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -820,7 +820,7 @@ iscsi_free_iscsi_in_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
|
|||||||
{
|
{
|
||||||
iscsi_free(iscsi, in->data);
|
iscsi_free(iscsi, in->data);
|
||||||
in->data=NULL;
|
in->data=NULL;
|
||||||
iscsi_free(iscsi, in);
|
iscsi_sfree(iscsi, in);
|
||||||
in=NULL;
|
in=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user