Commit 8f606604 authored by zijun_hu's avatar zijun_hu Committed by Linus Torvalds

mm/percpu.c: fix panic triggered by BUG_ON() falsely

As shown by pcpu_build_alloc_info(), the number of units within a percpu
group is deduced by rounding up the number of CPUs within the group to
@upa boundary/ Therefore, the number of CPUs isn't equal to the units's
if it isn't aligned to @upa normally.  However, pcpu_page_first_chunk()
uses BUG_ON() to assert that one number is equal to the other roughly,
so a panic is maybe triggered by the BUG_ON() incorrectly.

In order to fix this issue, the number of CPUs is rounded up then
compared with units's and the BUG_ON() is replaced with a warning and
return of an error code as well, to keep system alive as much as
possible.

Link: http://lkml.kernel.org/r/57FCF07C.2020103@zoho.comSigned-off-by: default avatarzijun_hu <zijun_hu@htc.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Christoph Lameter <cl@linux.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent c5caf21a
...@@ -2093,6 +2093,8 @@ int __init pcpu_page_first_chunk(size_t reserved_size, ...@@ -2093,6 +2093,8 @@ int __init pcpu_page_first_chunk(size_t reserved_size,
size_t pages_size; size_t pages_size;
struct page **pages; struct page **pages;
int unit, i, j, rc; int unit, i, j, rc;
int upa;
int nr_g0_units;
snprintf(psize_str, sizeof(psize_str), "%luK", PAGE_SIZE >> 10); snprintf(psize_str, sizeof(psize_str), "%luK", PAGE_SIZE >> 10);
...@@ -2100,7 +2102,12 @@ int __init pcpu_page_first_chunk(size_t reserved_size, ...@@ -2100,7 +2102,12 @@ int __init pcpu_page_first_chunk(size_t reserved_size,
if (IS_ERR(ai)) if (IS_ERR(ai))
return PTR_ERR(ai); return PTR_ERR(ai);
BUG_ON(ai->nr_groups != 1); BUG_ON(ai->nr_groups != 1);
BUG_ON(ai->groups[0].nr_units != num_possible_cpus()); upa = ai->alloc_size/ai->unit_size;
nr_g0_units = roundup(num_possible_cpus(), upa);
if (unlikely(WARN_ON(ai->groups[0].nr_units != nr_g0_units))) {
pcpu_free_alloc_info(ai);
return -EINVAL;
}
unit_pages = ai->unit_size >> PAGE_SHIFT; unit_pages = ai->unit_size >> PAGE_SHIFT;
...@@ -2111,21 +2118,22 @@ int __init pcpu_page_first_chunk(size_t reserved_size, ...@@ -2111,21 +2118,22 @@ int __init pcpu_page_first_chunk(size_t reserved_size,
/* allocate pages */ /* allocate pages */
j = 0; j = 0;
for (unit = 0; unit < num_possible_cpus(); unit++) for (unit = 0; unit < num_possible_cpus(); unit++) {
unsigned int cpu = ai->groups[0].cpu_map[unit];
for (i = 0; i < unit_pages; i++) { for (i = 0; i < unit_pages; i++) {
unsigned int cpu = ai->groups[0].cpu_map[unit];
void *ptr; void *ptr;
ptr = alloc_fn(cpu, PAGE_SIZE, PAGE_SIZE); ptr = alloc_fn(cpu, PAGE_SIZE, PAGE_SIZE);
if (!ptr) { if (!ptr) {
pr_warn("failed to allocate %s page for cpu%u\n", pr_warn("failed to allocate %s page for cpu%u\n",
psize_str, cpu); psize_str, cpu);
goto enomem; goto enomem;
} }
/* kmemleak tracks the percpu allocations separately */ /* kmemleak tracks the percpu allocations separately */
kmemleak_free(ptr); kmemleak_free(ptr);
pages[j++] = virt_to_page(ptr); pages[j++] = virt_to_page(ptr);
} }
}
/* allocate vm area, map the pages and copy static data */ /* allocate vm area, map the pages and copy static data */
vm.flags = VM_ALLOC; vm.flags = VM_ALLOC;
......
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