diff options
Diffstat (limited to 'net/core/flow.c')
-rw-r--r-- | net/core/flow.c | 22 |
1 files changed, 14 insertions, 8 deletions
diff --git a/net/core/flow.c b/net/core/flow.c index 96015871ecea..f032d1c37192 100644 --- a/net/core/flow.c +++ b/net/core/flow.c | |||
@@ -39,9 +39,10 @@ atomic_t flow_cache_genid = ATOMIC_INIT(0); | |||
39 | 39 | ||
40 | static u32 flow_hash_shift; | 40 | static u32 flow_hash_shift; |
41 | #define flow_hash_size (1 << flow_hash_shift) | 41 | #define flow_hash_size (1 << flow_hash_shift) |
42 | static DEFINE_PER_CPU(struct flow_cache_entry **, flow_tables) = { NULL }; | ||
43 | 42 | ||
44 | #define flow_table(cpu) (per_cpu(flow_tables, cpu)) | 43 | static DEFINE_PER_CPU_LOCKED(struct flow_cache_entry **, flow_tables); |
44 | |||
45 | #define flow_table(cpu) (per_cpu_var_locked(flow_tables, cpu)) | ||
45 | 46 | ||
46 | static struct kmem_cache *flow_cachep __read_mostly; | 47 | static struct kmem_cache *flow_cachep __read_mostly; |
47 | 48 | ||
@@ -168,24 +169,24 @@ static int flow_key_compare(struct flowi *key1, struct flowi *key2) | |||
168 | void *flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir, | 169 | void *flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir, |
169 | flow_resolve_t resolver) | 170 | flow_resolve_t resolver) |
170 | { | 171 | { |
171 | struct flow_cache_entry *fle, **head; | 172 | struct flow_cache_entry **table, *fle, **head; |
172 | unsigned int hash; | 173 | unsigned int hash; |
173 | int cpu; | 174 | int cpu; |
174 | 175 | ||
175 | local_bh_disable(); | 176 | local_bh_disable(); |
176 | cpu = smp_processor_id(); | 177 | table = get_cpu_var_locked(flow_tables, &cpu); |
177 | 178 | ||
178 | fle = NULL; | 179 | fle = NULL; |
179 | /* Packet really early in init? Making flow_cache_init a | 180 | /* Packet really early in init? Making flow_cache_init a |
180 | * pre-smp initcall would solve this. --RR */ | 181 | * pre-smp initcall would solve this. --RR */ |
181 | if (!flow_table(cpu)) | 182 | if (!table) |
182 | goto nocache; | 183 | goto nocache; |
183 | 184 | ||
184 | if (flow_hash_rnd_recalc(cpu)) | 185 | if (flow_hash_rnd_recalc(cpu)) |
185 | flow_new_hash_rnd(cpu); | 186 | flow_new_hash_rnd(cpu); |
186 | hash = flow_hash_code(key, cpu); | 187 | hash = flow_hash_code(key, cpu); |
187 | 188 | ||
188 | head = &flow_table(cpu)[hash]; | 189 | head = &table[hash]; |
189 | for (fle = *head; fle; fle = fle->next) { | 190 | for (fle = *head; fle; fle = fle->next) { |
190 | if (fle->family == family && | 191 | if (fle->family == family && |
191 | fle->dir == dir && | 192 | fle->dir == dir && |
@@ -195,6 +196,7 @@ void *flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir, | |||
195 | 196 | ||
196 | if (ret) | 197 | if (ret) |
197 | atomic_inc(fle->object_ref); | 198 | atomic_inc(fle->object_ref); |
199 | put_cpu_var_locked(flow_tables, cpu); | ||
198 | local_bh_enable(); | 200 | local_bh_enable(); |
199 | 201 | ||
200 | return ret; | 202 | return ret; |
@@ -220,6 +222,8 @@ void *flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir, | |||
220 | } | 222 | } |
221 | 223 | ||
222 | nocache: | 224 | nocache: |
225 | put_cpu_var_locked(flow_tables, cpu); | ||
226 | |||
223 | { | 227 | { |
224 | int err; | 228 | int err; |
225 | void *obj; | 229 | void *obj; |
@@ -249,14 +253,15 @@ nocache: | |||
249 | static void flow_cache_flush_tasklet(unsigned long data) | 253 | static void flow_cache_flush_tasklet(unsigned long data) |
250 | { | 254 | { |
251 | struct flow_flush_info *info = (void *)data; | 255 | struct flow_flush_info *info = (void *)data; |
256 | struct flow_cache_entry **table; | ||
252 | int i; | 257 | int i; |
253 | int cpu; | 258 | int cpu; |
254 | 259 | ||
255 | cpu = smp_processor_id(); | 260 | table = get_cpu_var_locked(flow_tables, &cpu); |
256 | for (i = 0; i < flow_hash_size; i++) { | 261 | for (i = 0; i < flow_hash_size; i++) { |
257 | struct flow_cache_entry *fle; | 262 | struct flow_cache_entry *fle; |
258 | 263 | ||
259 | fle = flow_table(cpu)[i]; | 264 | fle = table[i]; |
260 | for (; fle; fle = fle->next) { | 265 | for (; fle; fle = fle->next) { |
261 | unsigned genid = atomic_read(&flow_cache_genid); | 266 | unsigned genid = atomic_read(&flow_cache_genid); |
262 | 267 | ||
@@ -267,6 +272,7 @@ static void flow_cache_flush_tasklet(unsigned long data) | |||
267 | atomic_dec(fle->object_ref); | 272 | atomic_dec(fle->object_ref); |
268 | } | 273 | } |
269 | } | 274 | } |
275 | put_cpu_var_locked(flow_tables, cpu); | ||
270 | 276 | ||
271 | if (atomic_dec_and_test(&info->cpuleft)) | 277 | if (atomic_dec_and_test(&info->cpuleft)) |
272 | complete(&info->completion); | 278 | complete(&info->completion); |