percpu: replace pcpu_realloc() with pcpu_mem_alloc() and pcpu_mem_free()

Impact: code reorganization for later changes

With static map handling moved to pcpu_split_block(), pcpu_realloc()
only clutters the code and it's also unsuitable for scheduled locking
changes.  Implement and use pcpu_mem_alloc/free() instead.

Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
Tejun Heo 2009-03-07 00:44:09 +09:00
parent 6b19b0c240
commit 1880d93b80
1 changed files with 43 additions and 44 deletions

View File

@ -164,39 +164,41 @@ static bool pcpu_chunk_page_occupied(struct pcpu_chunk *chunk,
} }
/** /**
* pcpu_realloc - versatile realloc * pcpu_mem_alloc - allocate memory
* @p: the current pointer (can be NULL for new allocations) * @size: bytes to allocate
* @size: the current size in bytes (can be 0 for new allocations)
* @new_size: the wanted new size in bytes (can be 0 for free)
* *
* More robust realloc which can be used to allocate, resize or free a * Allocate @size bytes. If @size is smaller than PAGE_SIZE,
* memory area of arbitrary size. If the needed size goes over * kzalloc() is used; otherwise, vmalloc() is used. The returned
* PAGE_SIZE, kernel VM is used. * memory is always zeroed.
* *
* RETURNS: * RETURNS:
* The new pointer on success, NULL on failure. * Pointer to the allocated area on success, NULL on failure.
*/ */
static void *pcpu_realloc(void *p, size_t size, size_t new_size) static void *pcpu_mem_alloc(size_t size)
{ {
void *new;
if (new_size <= PAGE_SIZE)
new = kmalloc(new_size, GFP_KERNEL);
else
new = vmalloc(new_size);
if (new_size && !new)
return NULL;
memcpy(new, p, min(size, new_size));
if (new_size > size)
memset(new + size, 0, new_size - size);
if (size <= PAGE_SIZE) if (size <= PAGE_SIZE)
kfree(p); return kzalloc(size, GFP_KERNEL);
else else {
vfree(p); void *ptr = vmalloc(size);
if (ptr)
memset(ptr, 0, size);
return ptr;
}
}
return new; /**
* pcpu_mem_free - free memory
* @ptr: memory to free
* @size: size of the area
*
* Free @ptr. @ptr should have been allocated using pcpu_mem_alloc().
*/
static void pcpu_mem_free(void *ptr, size_t size)
{
if (size <= PAGE_SIZE)
kfree(ptr);
else
vfree(ptr);
} }
/** /**
@ -331,29 +333,27 @@ static int pcpu_split_block(struct pcpu_chunk *chunk, int i, int head, int tail)
if (chunk->map_alloc < target) { if (chunk->map_alloc < target) {
int new_alloc; int new_alloc;
int *new; int *new;
size_t size;
new_alloc = PCPU_DFL_MAP_ALLOC; new_alloc = PCPU_DFL_MAP_ALLOC;
while (new_alloc < target) while (new_alloc < target)
new_alloc *= 2; new_alloc *= 2;
if (chunk->map_alloc < PCPU_DFL_MAP_ALLOC) { new = pcpu_mem_alloc(new_alloc * sizeof(new[0]));
/*
* map_alloc smaller than the default size
* indicates that the chunk is one of the
* first chunks and still using static map.
* Allocate a dynamic one and copy.
*/
new = pcpu_realloc(NULL, 0, new_alloc * sizeof(new[0]));
if (new)
memcpy(new, chunk->map,
chunk->map_alloc * sizeof(new[0]));
} else
new = pcpu_realloc(chunk->map,
chunk->map_alloc * sizeof(new[0]),
new_alloc * sizeof(new[0]));
if (!new) if (!new)
return -ENOMEM; return -ENOMEM;
size = chunk->map_alloc * sizeof(chunk->map[0]);
memcpy(new, chunk->map, size);
/*
* map_alloc < PCPU_DFL_MAP_ALLOC indicates that the
* chunk is one of the first chunks and still using
* static map.
*/
if (chunk->map_alloc >= PCPU_DFL_MAP_ALLOC)
pcpu_mem_free(chunk->map, size);
chunk->map_alloc = new_alloc; chunk->map_alloc = new_alloc;
chunk->map = new; chunk->map = new;
} }
@ -696,7 +696,7 @@ static void free_pcpu_chunk(struct pcpu_chunk *chunk)
return; return;
if (chunk->vm) if (chunk->vm)
free_vm_area(chunk->vm); free_vm_area(chunk->vm);
pcpu_realloc(chunk->map, chunk->map_alloc * sizeof(chunk->map[0]), 0); pcpu_mem_free(chunk->map, chunk->map_alloc * sizeof(chunk->map[0]));
kfree(chunk); kfree(chunk);
} }
@ -708,8 +708,7 @@ static struct pcpu_chunk *alloc_pcpu_chunk(void)
if (!chunk) if (!chunk)
return NULL; return NULL;
chunk->map = pcpu_realloc(NULL, 0, chunk->map = pcpu_mem_alloc(PCPU_DFL_MAP_ALLOC * sizeof(chunk->map[0]));
PCPU_DFL_MAP_ALLOC * sizeof(chunk->map[0]));
chunk->map_alloc = PCPU_DFL_MAP_ALLOC; chunk->map_alloc = PCPU_DFL_MAP_ALLOC;
chunk->map[chunk->map_used++] = pcpu_unit_size; chunk->map[chunk->map_used++] = pcpu_unit_size;
chunk->page = chunk->page_ar; chunk->page = chunk->page_ar;