PDU reduce number of mallocs/memcpys in iscsi_add_data()
This patch adds logarithmic malloc behaviour to iscsi_add_data(). Currently for each new call there is a new buffer allocated and all old data is copied to the new buffer. Change this by allocating at least PAGE_SIZE bytes and increase the allocation by powers of 2 each time it does no longer fit.
This commit is contained in:
@@ -33,6 +33,7 @@ struct iscsi_context;
|
|||||||
struct sockaddr;
|
struct sockaddr;
|
||||||
|
|
||||||
#define MAX_STRING_SIZE (255)
|
#define MAX_STRING_SIZE (255)
|
||||||
|
#define PAGE_SIZE (4096)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Syntax for normal and portal/discovery URLs.
|
* Syntax for normal and portal/discovery URLs.
|
||||||
@@ -533,6 +534,7 @@ iscsi_task_mgmt_target_cold_reset_async(struct iscsi_context *iscsi,
|
|||||||
|
|
||||||
struct iscsi_data {
|
struct iscsi_data {
|
||||||
int size;
|
int size;
|
||||||
|
int alloc_size;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
29
lib/pdu.c
29
lib/pdu.c
@@ -107,7 +107,6 @@ iscsi_add_data(struct iscsi_context *iscsi, struct iscsi_data *data,
|
|||||||
unsigned char *dptr, int dsize, int pdualignment)
|
unsigned char *dptr, int dsize, int pdualignment)
|
||||||
{
|
{
|
||||||
int len, aligned;
|
int len, aligned;
|
||||||
unsigned char *buf;
|
|
||||||
|
|
||||||
if (dsize == 0) {
|
if (dsize == 0) {
|
||||||
iscsi_set_error(iscsi, "Trying to append zero size data to "
|
iscsi_set_error(iscsi, "Trying to append zero size data to "
|
||||||
@@ -121,25 +120,33 @@ iscsi_add_data(struct iscsi_context *iscsi, struct iscsi_data *data,
|
|||||||
aligned = (aligned+3)&0xfffffffc;
|
aligned = (aligned+3)&0xfffffffc;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = iscsi_malloc(iscsi, aligned);
|
int new_alloc_size=data->alloc_size;
|
||||||
if (buf == NULL) {
|
if (new_alloc_size < PAGE_SIZE) new_alloc_size=PAGE_SIZE;
|
||||||
|
|
||||||
|
while (aligned > new_alloc_size) new_alloc_size<<=1;
|
||||||
|
|
||||||
|
if (data->data != NULL && data->alloc_size == 0) data->alloc_size=data->size;
|
||||||
|
|
||||||
|
if (data->alloc_size == 0)
|
||||||
|
data->data = iscsi_malloc(iscsi, new_alloc_size);
|
||||||
|
else
|
||||||
|
if (data->alloc_size != new_alloc_size)
|
||||||
|
data->data = realloc(data->data, new_alloc_size);
|
||||||
|
|
||||||
|
if (data->data == NULL) {
|
||||||
iscsi_set_error(iscsi, "failed to allocate buffer for %d "
|
iscsi_set_error(iscsi, "failed to allocate buffer for %d "
|
||||||
"bytes", len);
|
"bytes", len);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->size > 0) {
|
data->alloc_size = new_alloc_size;
|
||||||
memcpy(buf, data->data, data->size);
|
memcpy(data->data + data->size, dptr, dsize);
|
||||||
}
|
|
||||||
memcpy(buf + data->size, dptr, dsize);
|
|
||||||
if (len != aligned) {
|
if (len != aligned) {
|
||||||
/* zero out any padding at the end */
|
/* zero out any padding at the end */
|
||||||
memset(buf+len, 0, aligned-len);
|
memset(data->data+len, 0, aligned-len);
|
||||||
}
|
}
|
||||||
|
|
||||||
iscsi_free(iscsi, data->data);
|
|
||||||
|
|
||||||
data->data = buf;
|
|
||||||
data->size = len;
|
data->size = len;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user