Commit 1880d93b80acc3171850e9df5048bcb26b75c2f5
1 parent
6b19b0c240
Exists in
master
and in
20 other branches
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>
Showing 1 changed file with 42 additions and 43 deletions Side-by-side Diff
mm/percpu.c
... | ... | @@ -164,39 +164,41 @@ |
164 | 164 | } |
165 | 165 | |
166 | 166 | /** |
167 | - * pcpu_realloc - versatile realloc | |
168 | - * @p: the current pointer (can be NULL for new allocations) | |
169 | - * @size: the current size in bytes (can be 0 for new allocations) | |
170 | - * @new_size: the wanted new size in bytes (can be 0 for free) | |
167 | + * pcpu_mem_alloc - allocate memory | |
168 | + * @size: bytes to allocate | |
171 | 169 | * |
172 | - * More robust realloc which can be used to allocate, resize or free a | |
173 | - * memory area of arbitrary size. If the needed size goes over | |
174 | - * PAGE_SIZE, kernel VM is used. | |
170 | + * Allocate @size bytes. If @size is smaller than PAGE_SIZE, | |
171 | + * kzalloc() is used; otherwise, vmalloc() is used. The returned | |
172 | + * memory is always zeroed. | |
175 | 173 | * |
176 | 174 | * RETURNS: |
177 | - * The new pointer on success, NULL on failure. | |
175 | + * Pointer to the allocated area on success, NULL on failure. | |
178 | 176 | */ |
179 | -static void *pcpu_realloc(void *p, size_t size, size_t new_size) | |
177 | +static void *pcpu_mem_alloc(size_t size) | |
180 | 178 | { |
181 | - void *new; | |
179 | + if (size <= PAGE_SIZE) | |
180 | + return kzalloc(size, GFP_KERNEL); | |
181 | + else { | |
182 | + void *ptr = vmalloc(size); | |
183 | + if (ptr) | |
184 | + memset(ptr, 0, size); | |
185 | + return ptr; | |
186 | + } | |
187 | +} | |
182 | 188 | |
183 | - if (new_size <= PAGE_SIZE) | |
184 | - new = kmalloc(new_size, GFP_KERNEL); | |
185 | - else | |
186 | - new = vmalloc(new_size); | |
187 | - if (new_size && !new) | |
188 | - return NULL; | |
189 | - | |
190 | - memcpy(new, p, min(size, new_size)); | |
191 | - if (new_size > size) | |
192 | - memset(new + size, 0, new_size - size); | |
193 | - | |
189 | +/** | |
190 | + * pcpu_mem_free - free memory | |
191 | + * @ptr: memory to free | |
192 | + * @size: size of the area | |
193 | + * | |
194 | + * Free @ptr. @ptr should have been allocated using pcpu_mem_alloc(). | |
195 | + */ | |
196 | +static void pcpu_mem_free(void *ptr, size_t size) | |
197 | +{ | |
194 | 198 | if (size <= PAGE_SIZE) |
195 | - kfree(p); | |
199 | + kfree(ptr); | |
196 | 200 | else |
197 | - vfree(p); | |
198 | - | |
199 | - return new; | |
201 | + vfree(ptr); | |
200 | 202 | } |
201 | 203 | |
202 | 204 | /** |
203 | 205 | |
204 | 206 | |
... | ... | @@ -331,29 +333,27 @@ |
331 | 333 | if (chunk->map_alloc < target) { |
332 | 334 | int new_alloc; |
333 | 335 | int *new; |
336 | + size_t size; | |
334 | 337 | |
335 | 338 | new_alloc = PCPU_DFL_MAP_ALLOC; |
336 | 339 | while (new_alloc < target) |
337 | 340 | new_alloc *= 2; |
338 | 341 | |
339 | - if (chunk->map_alloc < PCPU_DFL_MAP_ALLOC) { | |
340 | - /* | |
341 | - * map_alloc smaller than the default size | |
342 | - * indicates that the chunk is one of the | |
343 | - * first chunks and still using static map. | |
344 | - * Allocate a dynamic one and copy. | |
345 | - */ | |
346 | - new = pcpu_realloc(NULL, 0, new_alloc * sizeof(new[0])); | |
347 | - if (new) | |
348 | - memcpy(new, chunk->map, | |
349 | - chunk->map_alloc * sizeof(new[0])); | |
350 | - } else | |
351 | - new = pcpu_realloc(chunk->map, | |
352 | - chunk->map_alloc * sizeof(new[0]), | |
353 | - new_alloc * sizeof(new[0])); | |
342 | + new = pcpu_mem_alloc(new_alloc * sizeof(new[0])); | |
354 | 343 | if (!new) |
355 | 344 | return -ENOMEM; |
356 | 345 | |
346 | + size = chunk->map_alloc * sizeof(chunk->map[0]); | |
347 | + memcpy(new, chunk->map, size); | |
348 | + | |
349 | + /* | |
350 | + * map_alloc < PCPU_DFL_MAP_ALLOC indicates that the | |
351 | + * chunk is one of the first chunks and still using | |
352 | + * static map. | |
353 | + */ | |
354 | + if (chunk->map_alloc >= PCPU_DFL_MAP_ALLOC) | |
355 | + pcpu_mem_free(chunk->map, size); | |
356 | + | |
357 | 357 | chunk->map_alloc = new_alloc; |
358 | 358 | chunk->map = new; |
359 | 359 | } |
... | ... | @@ -696,7 +696,7 @@ |
696 | 696 | return; |
697 | 697 | if (chunk->vm) |
698 | 698 | free_vm_area(chunk->vm); |
699 | - pcpu_realloc(chunk->map, chunk->map_alloc * sizeof(chunk->map[0]), 0); | |
699 | + pcpu_mem_free(chunk->map, chunk->map_alloc * sizeof(chunk->map[0])); | |
700 | 700 | kfree(chunk); |
701 | 701 | } |
702 | 702 | |
... | ... | @@ -708,8 +708,7 @@ |
708 | 708 | if (!chunk) |
709 | 709 | return NULL; |
710 | 710 | |
711 | - chunk->map = pcpu_realloc(NULL, 0, | |
712 | - PCPU_DFL_MAP_ALLOC * sizeof(chunk->map[0])); | |
711 | + chunk->map = pcpu_mem_alloc(PCPU_DFL_MAP_ALLOC * sizeof(chunk->map[0])); | |
713 | 712 | chunk->map_alloc = PCPU_DFL_MAP_ALLOC; |
714 | 713 | chunk->map[chunk->map_used++] = pcpu_unit_size; |
715 | 714 | chunk->page = chunk->page_ar; |