Commit 6b8f651f authored by Pavel Emelyanov's avatar Pavel Emelyanov

rst-mem: Grow buffer more than 2 pages if required

Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent a2917ffc
...@@ -11,7 +11,7 @@ struct rst_mem_type_s { ...@@ -11,7 +11,7 @@ struct rst_mem_type_s {
bool enabled; bool enabled;
unsigned long free_bytes; unsigned long free_bytes;
void *free_mem; void *free_mem;
int (*grow)(struct rst_mem_type_s *); int (*grow)(struct rst_mem_type_s *, unsigned long size);
unsigned long last; unsigned long last;
void *buf; void *buf;
...@@ -20,37 +20,51 @@ struct rst_mem_type_s { ...@@ -20,37 +20,51 @@ struct rst_mem_type_s {
#define RST_MEM_BATCH (2 * PAGE_SIZE) #define RST_MEM_BATCH (2 * PAGE_SIZE)
static int grow_shared(struct rst_mem_type_s *t) static inline unsigned long rst_mem_grow(unsigned long need_size)
{
need_size = round_up(need_size, PAGE_SIZE);
if (likely(need_size < RST_MEM_BATCH))
need_size = RST_MEM_BATCH;
else
pr_debug("Growing rst memory %lu pages\n", need_size / PAGE_SIZE);
return need_size;
}
static int grow_shared(struct rst_mem_type_s *t, unsigned long size)
{ {
void *aux; void *aux;
size = rst_mem_grow(size);
/* /*
* This buffer will not get remapped into * This buffer will not get remapped into
* restorer, thus we can just forget the * restorer, thus we can just forget the
* previous chunk location and allocate a * previous chunk location and allocate a
* new one * new one
*/ */
aux = mmap(NULL, RST_MEM_BATCH, PROT_READ | PROT_WRITE, aux = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANON, 0, 0); MAP_SHARED | MAP_ANON, 0, 0);
if (aux == MAP_FAILED) if (aux == MAP_FAILED)
return -1; return -1;
t->free_mem = aux; t->free_mem = aux;
t->free_bytes = RST_MEM_BATCH; t->free_bytes = size;
t->last = 0; t->last = 0;
return 0; return 0;
} }
static int grow_remap(struct rst_mem_type_s *t, int flag) static int grow_remap(struct rst_mem_type_s *t, int flag, unsigned long size)
{ {
void *aux; void *aux;
size = rst_mem_grow(size);
if (!t->buf) if (!t->buf)
/* /*
* Can't call mremap with NULL address :( * Can't call mremap with NULL address :(
*/ */
aux = mmap(NULL, RST_MEM_BATCH, PROT_READ | PROT_WRITE, aux = mmap(NULL, size, PROT_READ | PROT_WRITE,
flag | MAP_ANON, 0, 0); flag | MAP_ANON, 0, 0);
else else
/* /*
...@@ -63,26 +77,26 @@ static int grow_remap(struct rst_mem_type_s *t, int flag) ...@@ -63,26 +77,26 @@ static int grow_remap(struct rst_mem_type_s *t, int flag)
* cpos-s. * cpos-s.
*/ */
aux = mremap(t->buf, t->size, aux = mremap(t->buf, t->size,
t->size + RST_MEM_BATCH, MREMAP_MAYMOVE); t->size + size, MREMAP_MAYMOVE);
if (aux == MAP_FAILED) if (aux == MAP_FAILED)
return -1; return -1;
t->free_mem += (aux - t->buf); t->free_mem += (aux - t->buf);
t->free_bytes += RST_MEM_BATCH; t->free_bytes += size;
t->size += RST_MEM_BATCH; t->size += size;
t->buf = aux; t->buf = aux;
return 0; return 0;
} }
static int grow_shremap(struct rst_mem_type_s *t) static int grow_shremap(struct rst_mem_type_s *t, unsigned long size)
{ {
return grow_remap(t, MAP_SHARED); return grow_remap(t, MAP_SHARED, size);
} }
static int grow_private(struct rst_mem_type_s *t) static int grow_private(struct rst_mem_type_s *t, unsigned long size)
{ {
return grow_remap(t, MAP_PRIVATE); return grow_remap(t, MAP_PRIVATE, size);
} }
static struct rst_mem_type_s rst_mems[RST_MEM_TYPES] = { static struct rst_mem_type_s rst_mems[RST_MEM_TYPES] = {
...@@ -131,7 +145,7 @@ void *rst_mem_alloc(unsigned long size, int type) ...@@ -131,7 +145,7 @@ void *rst_mem_alloc(unsigned long size, int type)
BUG_ON(!t->enabled); BUG_ON(!t->enabled);
if ((t->free_bytes < size) && t->grow(t)) { if ((t->free_bytes < size) && t->grow(t, size)) {
pr_perror("Can't grow rst mem"); pr_perror("Can't grow rst mem");
return NULL; return NULL;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment