From: Martin Hicks Once NR_CPUS exceeds about 300 ext2 and ext3 will not compile, because the percpu counters in the superblocks are so huge that they cannot be kmalloced. Fix this by converting the percpu_counter mechanism to use alloc_percpu() rather than an NR_CPUS-sized array. include/linux/percpu_counter.h | 21 ++++++++++++--------- mm/swap.c | 8 +++++--- 2 files changed, 17 insertions(+), 12 deletions(-) diff -puN include/linux/percpu_counter.h~percpu_counter-use-alloc_percpu include/linux/percpu_counter.h --- 25/include/linux/percpu_counter.h~percpu_counter-use-alloc_percpu 2003-11-09 23:56:29.000000000 -0800 +++ 25-akpm/include/linux/percpu_counter.h 2003-11-10 00:03:24.000000000 -0800 @@ -8,17 +8,14 @@ #include #include #include +#include #ifdef CONFIG_SMP -struct __percpu_counter { - long count; -} ____cacheline_aligned; - struct percpu_counter { spinlock_t lock; long count; - struct __percpu_counter counters[NR_CPUS]; + long *counters; }; #if NR_CPUS >= 16 @@ -29,12 +26,14 @@ struct percpu_counter { static inline void percpu_counter_init(struct percpu_counter *fbc) { - int i; - spin_lock_init(&fbc->lock); fbc->count = 0; - for (i = 0; i < NR_CPUS; i++) - fbc->counters[i].count = 0; + fbc->counters = alloc_percpu(long); +} + +static inline void percpu_counter_destroy(struct percpu_counter *fbc) +{ + free_percpu(fbc->counters); } void percpu_counter_mod(struct percpu_counter *fbc, long amount); @@ -69,6 +68,10 @@ static inline void percpu_counter_init(s fbc->count = 0; } +static inline void percpu_counter_destroy(struct percpu_counter *fbc) +{ +} + static inline void percpu_counter_mod(struct percpu_counter *fbc, long amount) { diff -puN mm/swap.c~percpu_counter-use-alloc_percpu mm/swap.c --- 25/mm/swap.c~percpu_counter-use-alloc_percpu 2003-11-09 23:56:29.000000000 -0800 +++ 25-akpm/mm/swap.c 2003-11-10 00:03:51.000000000 -0800 @@ -386,17 +386,19 @@ EXPORT_SYMBOL(vm_acct_memory); #ifdef CONFIG_SMP void percpu_counter_mod(struct percpu_counter *fbc, long amount) { + long count; + long *pcount; int cpu = get_cpu(); - long count = fbc->counters[cpu].count; - count += amount; + pcount = per_cpu_ptr(fbc->counters, cpu); + count = *pcount + amount; if (count >= FBC_BATCH || count <= -FBC_BATCH) { spin_lock(&fbc->lock); fbc->count += count; spin_unlock(&fbc->lock); count = 0; } - fbc->counters[cpu].count = count; + *pcount = count; put_cpu(); } EXPORT_SYMBOL(percpu_counter_mod); _