diff options
Diffstat (limited to 'mm/percpu.c')
| -rw-r--r-- | mm/percpu.c | 22 | 
1 files changed, 17 insertions, 5 deletions
diff --git a/mm/percpu.c b/mm/percpu.c index f47af9123af..bb4be7435ce 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -1132,20 +1132,20 @@ static void pcpu_dump_alloc_info(const char *lvl,  		for (alloc_end += gi->nr_units / upa;  		     alloc < alloc_end; alloc++) {  			if (!(alloc % apl)) { -				printk("\n"); +				printk(KERN_CONT "\n");  				printk("%spcpu-alloc: ", lvl);  			} -			printk("[%0*d] ", group_width, group); +			printk(KERN_CONT "[%0*d] ", group_width, group);  			for (unit_end += upa; unit < unit_end; unit++)  				if (gi->cpu_map[unit] != NR_CPUS) -					printk("%0*d ", cpu_width, +					printk(KERN_CONT "%0*d ", cpu_width,  					       gi->cpu_map[unit]);  				else -					printk("%s ", empty_str); +					printk(KERN_CONT "%s ", empty_str);  		}  	} -	printk("\n"); +	printk(KERN_CONT "\n");  }  /** @@ -1650,6 +1650,16 @@ int __init pcpu_embed_first_chunk(size_t reserved_size, size_t dyn_size,  		areas[group] = ptr;  		base = min(ptr, base); +	} + +	/* +	 * Copy data and free unused parts.  This should happen after all +	 * allocations are complete; otherwise, we may end up with +	 * overlapping groups. +	 */ +	for (group = 0; group < ai->nr_groups; group++) { +		struct pcpu_group_info *gi = &ai->groups[group]; +		void *ptr = areas[group];  		for (i = 0; i < gi->nr_units; i++, ptr += ai->unit_size) {  			if (gi->cpu_map[i] == NR_CPUS) { @@ -1885,6 +1895,8 @@ void __init setup_per_cpu_areas(void)  	fc = __alloc_bootmem(unit_size, PAGE_SIZE, __pa(MAX_DMA_ADDRESS));  	if (!ai || !fc)  		panic("Failed to allocate memory for percpu areas."); +	/* kmemleak tracks the percpu allocations separately */ +	kmemleak_free(fc);  	ai->dyn_size = unit_size;  	ai->unit_size = unit_size;  |