Commit 22565897 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] use alloc_percpu in percpu_counters

From: Martin Hicks <mort@wildopensource.com>

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.
parent 55e8b1a1
...@@ -8,17 +8,14 @@ ...@@ -8,17 +8,14 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/percpu.h>
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
struct __percpu_counter {
long count;
} ____cacheline_aligned;
struct percpu_counter { struct percpu_counter {
spinlock_t lock; spinlock_t lock;
long count; long count;
struct __percpu_counter counters[NR_CPUS]; long *counters;
}; };
#if NR_CPUS >= 16 #if NR_CPUS >= 16
...@@ -29,12 +26,14 @@ struct percpu_counter { ...@@ -29,12 +26,14 @@ struct percpu_counter {
static inline void percpu_counter_init(struct percpu_counter *fbc) static inline void percpu_counter_init(struct percpu_counter *fbc)
{ {
int i;
spin_lock_init(&fbc->lock); spin_lock_init(&fbc->lock);
fbc->count = 0; fbc->count = 0;
for (i = 0; i < NR_CPUS; i++) fbc->counters = alloc_percpu(long);
fbc->counters[i].count = 0; }
static inline void percpu_counter_destroy(struct percpu_counter *fbc)
{
free_percpu(fbc->counters);
} }
void percpu_counter_mod(struct percpu_counter *fbc, long amount); void percpu_counter_mod(struct percpu_counter *fbc, long amount);
...@@ -69,6 +68,10 @@ static inline void percpu_counter_init(struct percpu_counter *fbc) ...@@ -69,6 +68,10 @@ static inline void percpu_counter_init(struct percpu_counter *fbc)
fbc->count = 0; fbc->count = 0;
} }
static inline void percpu_counter_destroy(struct percpu_counter *fbc)
{
}
static inline void static inline void
percpu_counter_mod(struct percpu_counter *fbc, long amount) percpu_counter_mod(struct percpu_counter *fbc, long amount)
{ {
......
...@@ -386,17 +386,19 @@ EXPORT_SYMBOL(vm_acct_memory); ...@@ -386,17 +386,19 @@ EXPORT_SYMBOL(vm_acct_memory);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
void percpu_counter_mod(struct percpu_counter *fbc, long amount) void percpu_counter_mod(struct percpu_counter *fbc, long amount)
{ {
long count;
long *pcount;
int cpu = get_cpu(); 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) { if (count >= FBC_BATCH || count <= -FBC_BATCH) {
spin_lock(&fbc->lock); spin_lock(&fbc->lock);
fbc->count += count; fbc->count += count;
spin_unlock(&fbc->lock); spin_unlock(&fbc->lock);
count = 0; count = 0;
} }
fbc->counters[cpu].count = count; *pcount = count;
put_cpu(); put_cpu();
} }
EXPORT_SYMBOL(percpu_counter_mod); EXPORT_SYMBOL(percpu_counter_mod);
......
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