From: Andrew Morton Implement percpu_counter_sum(). This is a more accurate but slower version of percpu_counter_read_positive(). We need this for Alex's speedup-ext3_statfs patch. Otherwise it would be too inaccurate on large CPU counts. (Note that this makes Ravi's optimisation of removing percpu_counter.lock invalid. We need that lock to prevent other CPUs from making large changes to the accumulators). Cc: Ravikiran G Thirumalai Cc: Alex Tomas Signed-off-by: Andrew Morton --- include/linux/percpu_counter.h | 6 ++++++ mm/swap.c | 25 +++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff -puN include/linux/percpu_counter.h~percpu_counter_sum include/linux/percpu_counter.h --- devel/include/linux/percpu_counter.h~percpu_counter_sum 2006-02-27 20:58:17.000000000 -0800 +++ devel-akpm/include/linux/percpu_counter.h 2006-02-27 20:58:17.000000000 -0800 @@ -39,6 +39,7 @@ static inline void percpu_counter_destro } void percpu_counter_mod(struct percpu_counter *fbc, long amount); +long percpu_counter_sum(struct percpu_counter *fbc); static inline long percpu_counter_read(struct percpu_counter *fbc) { @@ -92,6 +93,11 @@ static inline long percpu_counter_read_p return fbc->count; } +static inline long percpu_counter_sum(struct percpu_counter *fbc) +{ + return percpu_counter_read_positive(fbc); +} + #endif /* CONFIG_SMP */ static inline void percpu_counter_inc(struct percpu_counter *fbc) diff -puN mm/swap.c~percpu_counter_sum mm/swap.c --- devel/mm/swap.c~percpu_counter_sum 2006-02-27 20:58:17.000000000 -0800 +++ devel-akpm/mm/swap.c 2006-02-27 20:58:17.000000000 -0800 @@ -531,13 +531,34 @@ void percpu_counter_mod(struct percpu_co if (count >= FBC_BATCH || count <= -FBC_BATCH) { spin_lock(&fbc->lock); fbc->count += count; + *pcount = 0; spin_unlock(&fbc->lock); - count = 0; + } else { + *pcount = count; } - *pcount = count; put_cpu(); } EXPORT_SYMBOL(percpu_counter_mod); + +/* + * Add up all the per-cpu counts, return the result. This is a more accurate + * but much slower version of percpu_counter_read_positive() + */ +long percpu_counter_sum(struct percpu_counter *fbc) +{ + long ret; + int cpu; + + spin_lock(&fbc->lock); + ret = fbc->count; + for_each_cpu(cpu) { + long *pcount = per_cpu_ptr(fbc->counters, cpu); + ret += *pcount; + } + spin_unlock(&fbc->lock); + return ret < 0 ? 0 : ret; +} +EXPORT_SYMBOL(percpu_counter_sum); #endif /* _