diff options
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/flow.c | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/net/core/flow.c b/net/core/flow.c index f23e7e386543..b16d31ae5e54 100644 --- a/net/core/flow.c +++ b/net/core/flow.c | |||
@@ -85,6 +85,14 @@ static void flow_cache_new_hashrnd(unsigned long arg) | |||
85 | add_timer(&flow_hash_rnd_timer); | 85 | add_timer(&flow_hash_rnd_timer); |
86 | } | 86 | } |
87 | 87 | ||
88 | static void flow_entry_kill(int cpu, struct flow_cache_entry *fle) | ||
89 | { | ||
90 | if (fle->object) | ||
91 | atomic_dec(fle->object_ref); | ||
92 | kmem_cache_free(flow_cachep, fle); | ||
93 | flow_count(cpu)--; | ||
94 | } | ||
95 | |||
88 | static void __flow_cache_shrink(int cpu, int shrink_to) | 96 | static void __flow_cache_shrink(int cpu, int shrink_to) |
89 | { | 97 | { |
90 | struct flow_cache_entry *fle, **flp; | 98 | struct flow_cache_entry *fle, **flp; |
@@ -100,10 +108,7 @@ static void __flow_cache_shrink(int cpu, int shrink_to) | |||
100 | } | 108 | } |
101 | while ((fle = *flp) != NULL) { | 109 | while ((fle = *flp) != NULL) { |
102 | *flp = fle->next; | 110 | *flp = fle->next; |
103 | if (fle->object) | 111 | flow_entry_kill(cpu, fle); |
104 | atomic_dec(fle->object_ref); | ||
105 | kmem_cache_free(flow_cachep, fle); | ||
106 | flow_count(cpu)--; | ||
107 | } | 112 | } |
108 | } | 113 | } |
109 | } | 114 | } |
@@ -220,24 +225,33 @@ void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, | |||
220 | 225 | ||
221 | nocache: | 226 | nocache: |
222 | { | 227 | { |
228 | int err; | ||
223 | void *obj; | 229 | void *obj; |
224 | atomic_t *obj_ref; | 230 | atomic_t *obj_ref; |
225 | 231 | ||
226 | resolver(key, family, dir, &obj, &obj_ref); | 232 | err = resolver(key, family, dir, &obj, &obj_ref); |
227 | 233 | ||
228 | if (fle) { | 234 | if (fle) { |
229 | fle->genid = atomic_read(&flow_cache_genid); | 235 | if (err) { |
230 | 236 | /* Force security policy check on next lookup */ | |
231 | if (fle->object) | 237 | *head = fle->next; |
232 | atomic_dec(fle->object_ref); | 238 | flow_entry_kill(cpu, fle); |
233 | 239 | } else { | |
234 | fle->object = obj; | 240 | fle->genid = atomic_read(&flow_cache_genid); |
235 | fle->object_ref = obj_ref; | 241 | |
236 | if (obj) | 242 | if (fle->object) |
237 | atomic_inc(fle->object_ref); | 243 | atomic_dec(fle->object_ref); |
244 | |||
245 | fle->object = obj; | ||
246 | fle->object_ref = obj_ref; | ||
247 | if (obj) | ||
248 | atomic_inc(fle->object_ref); | ||
249 | } | ||
238 | } | 250 | } |
239 | local_bh_enable(); | 251 | local_bh_enable(); |
240 | 252 | ||
253 | if (err) | ||
254 | obj = ERR_PTR(err); | ||
241 | return obj; | 255 | return obj; |
242 | } | 256 | } |
243 | } | 257 | } |