diff options
Diffstat (limited to 'net/core/dst.c')
-rw-r--r-- | net/core/dst.c | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/net/core/dst.c b/net/core/dst.c index 8ebdb0bb5..e94ef2967 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -58,38 +58,43 @@ static void dst_run_gc(unsigned long dummy) dst_gc_timer_inc += DST_GC_INC; dst_gc_timer.expires = jiffies + dst_gc_timer_expires; #if RT_CACHE_DEBUG >= 2 - printk("dst_total: %d/%d/%d %ld\n", - atomic_read(&dst_total), delayed, - atomic_read(&hh_count), dst_gc_timer_expires); + printk("dst_total: %d/%d %ld\n", + atomic_read(&dst_total), delayed, dst_gc_timer_expires); #endif add_timer(&dst_gc_timer); } static int dst_discard(struct sk_buff *skb) { - kfree_skb(skb, FREE_READ); + kfree_skb(skb); return 0; } static int dst_blackhole(struct sk_buff *skb) { - kfree_skb(skb, FREE_WRITE); + kfree_skb(skb); return 0; } void * dst_alloc(int size, struct dst_ops * ops) { struct dst_entry * dst; + + if (ops->gc && atomic_read(&ops->entries) > ops->gc_thresh) { + if (ops->gc()) + return NULL; + } dst = kmalloc(size, GFP_ATOMIC); if (!dst) return NULL; memset(dst, 0, size); dst->ops = ops; - atomic_set(&dst->refcnt, 1); + atomic_set(&dst->refcnt, 0); dst->lastuse = jiffies; dst->input = dst_discard; dst->output = dst_blackhole; atomic_inc(&dst_total); + atomic_inc(&ops->entries); return dst; } @@ -108,3 +113,25 @@ void __dst_free(struct dst_entry * dst) } end_bh_atomic(); } + +void dst_destroy(struct dst_entry * dst) +{ + struct neighbour *neigh = dst->neighbour; + struct hh_cache *hh = dst->hh; + + dst->hh = NULL; + if (hh && atomic_dec_and_test(&hh->hh_refcnt)) + kfree(hh); + + if (neigh) { + dst->neighbour = NULL; + neigh_release(neigh); + } + + atomic_dec(&dst->ops->entries); + + if (dst->ops->destroy) + dst->ops->destroy(dst); + atomic_dec(&dst_total); + kfree(dst); +} |