#define flow_table(cpu) (per_cpu(flow_tables, cpu))
-static kmem_cache_t *flow_cachep __read_mostly;
+static struct kmem_cache *flow_cachep __read_mostly;
static int flow_lwm, flow_hwm;
add_timer(&flow_hash_rnd_timer);
}
+static void flow_entry_kill(int cpu, struct flow_cache_entry *fle)
+{
+ if (fle->object)
+ atomic_dec(fle->object_ref);
+ kmem_cache_free(flow_cachep, fle);
+ flow_count(cpu)--;
+}
+
static void __flow_cache_shrink(int cpu, int shrink_to)
{
struct flow_cache_entry *fle, **flp;
}
while ((fle = *flp) != NULL) {
*flp = fle->next;
- if (fle->object)
- atomic_dec(fle->object_ref);
- kmem_cache_free(flow_cachep, fle);
- flow_count(cpu)--;
+ flow_entry_kill(cpu, fle);
}
}
}
if (flow_count(cpu) > flow_hwm)
flow_cache_shrink(cpu);
- fle = kmem_cache_alloc(flow_cachep, SLAB_ATOMIC);
+ fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC);
if (fle) {
fle->next = *head;
*head = fle;
nocache:
{
+ int err;
void *obj;
atomic_t *obj_ref;
- resolver(key, family, dir, &obj, &obj_ref);
+ err = resolver(key, family, dir, &obj, &obj_ref);
- if (fle) {
+ if (fle && !err) {
fle->genid = atomic_read(&flow_cache_genid);
if (fle->object)
}
local_bh_enable();
+ if (err)
+ obj = ERR_PTR(err);
return obj;
}
}
tasklet_init(tasklet, flow_cache_flush_tasklet, 0);
}
-#ifdef CONFIG_HOTPLUG_CPU
static int flow_cache_cpu(struct notifier_block *nfb,
unsigned long action,
void *hcpu)
__flow_cache_shrink((unsigned long)hcpu, 0);
return NOTIFY_OK;
}
-#endif /* CONFIG_HOTPLUG_CPU */
static int __init flow_cache_init(void)
{