From 7360c6e9f099c5ca2e8d740c2716e05f28fdd381 Mon Sep 17 00:00:00 2001 From: Michael Blizek Date: Thu, 22 Apr 2010 07:44:33 +0200 Subject: [PATCH] neighbor reference counter --- net/cor/neighbor.c | 4 ++-- net/cor/snd.c | 57 +++++++++++++++++++++++++++--------------------------- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/net/cor/neighbor.c b/net/cor/neighbor.c index 15f83d31c7e..2526c5ac79f 100644 --- a/net/cor/neighbor.c +++ b/net/cor/neighbor.c @@ -93,7 +93,7 @@ static int get_addrtype(__u32 addrtypelen, char *addrtype) void neighbor_free(struct kref *ref) { struct neighbor *nb = container_of(ref, struct neighbor, ref); - /* printk(KERN_ERR "neighbor free");*/ + printk(KERN_ERR "neighbor free"); BUG_ON(nb->nb_list.next != LIST_POISON1); BUG_ON(nb->nb_list.prev != LIST_POISON2); if (nb->addr != 0) @@ -108,7 +108,6 @@ void neighbor_free(struct kref *ref) static struct neighbor *alloc_neighbor(gfp_t allocflags) { struct neighbor *nb = kmem_cache_alloc(nb_slab, allocflags); - __u32 seqno; if (nb == 0) @@ -595,6 +594,7 @@ static void add_neighbor(struct neighbor *nb) currlh = currlh->next; } /* kref_get not needed here, because the caller leaves its ref to us */ + printk(KERN_ERR "add_neigh"); list_add_tail(&(nb->nb_list), &nb_list); schedule_controlmsg_timerfunc(nb); setup_timer(&(nb->retrans_timer), retransmit_timerfunc, diff --git a/net/cor/snd.c b/net/cor/snd.c index ae13d103e07..67fc5c29a9b 100644 --- a/net/cor/snd.c +++ b/net/cor/snd.c @@ -32,6 +32,7 @@ static void free_skb(struct kref *ref) funcstate.retransmit_queue.ref); struct sk_buff *skb = skb_from_pstate(ps); + kref_put(&(ps->funcstate.retransmit_queue.nb->ref), neighbor_free); kfree_skb(skb); } @@ -154,9 +155,6 @@ static void cor_xmit(struct sk_buff *skb, int atomic, int clone) return; } } else { - struct skb_procstate *ps = skb_pstate(skb); - kref_put(&(ps->funcstate.retransmit_queue.nb->ref), - neighbor_free); skb2 = skb; } @@ -179,6 +177,7 @@ void retransmit_timerfunc(unsigned long arg) unsigned long timeout; int nbstate; + int nbput = 0; spin_lock_irqsave( &(nb->state_lock), iflags ); nbstate = nb->state; @@ -193,9 +192,17 @@ void retransmit_timerfunc(unsigned long arg) if (nbstate == NEIGHBOR_STATE_KILLED) { struct skb_procstate *ps = skb_pstate(skb); + struct retransmit_matchparam rm; spin_unlock_irqrestore( &(nb->retrans_lock), iflags ); - kref_put(&(ps->funcstate.retransmit_queue.nb->ref), - neighbor_free); + + rm.conn_id = ps->funcstate.retransmit_queue.conn_id; + rm.seqno = ps->funcstate.retransmit_queue.seqno; + rm.nb = ps->funcstate.retransmit_queue.nb; + + htable_delete(&retransmits, rm_to_key(&rm), &rm, + free_skb); + kref_put(&(ps->funcstate.retransmit_queue.ref), + free_skb); continue; } @@ -220,9 +227,13 @@ modtimer: if (0) { out: nb->retrans_timer_running = 0; - kref_put(&(nb->ref), neighbor_free); + nbput = 1; + } spin_unlock_irqrestore( &(nb->retrans_lock), iflags ); + + if (nbput) + kref_put(&(nb->ref), neighbor_free); } static struct sk_buff *create_packet(struct neighbor *nb, int size, @@ -253,7 +264,7 @@ static struct sk_buff *create_packet(struct neighbor *nb, int size, ps->funcstate.retransmit_queue.conn_id = conn_id; ps->funcstate.retransmit_queue.seqno = seqno; ps->funcstate.retransmit_queue.nb = nb; - kref_get(&(nb->ref)); + /* nb_ref is in schedule_retransmit */ dest = skb_put(ret, 9); BUG_ON(0 == dest); @@ -352,29 +363,31 @@ void ack_received(struct neighbor *nb, __u32 conn_id, __u32 seqno) struct sk_buff *skb = 0; struct skb_procstate *ps; struct retransmit_matchparam rm; - + int first = 0; - + int ret; - + rm.conn_id = conn_id; rm.seqno = seqno; rm.nb = nb; - + skb = (struct sk_buff *) htable_get(&retransmits, rm_to_key(&rm), &rm); if (0 == skb) { printk(KERN_ERR "bogus/duplicate ack received"); return; } - + ps = skb_pstate(skb); - + ret = htable_delete(&retransmits, rm_to_key(&rm), &rm, free_skb); if (ret) { /* somebody else has already deleted it in the meantime */ return; } + + BUG_ON(ps->funcstate.retransmit_queue.nb != nb); spin_lock_irqsave( &(nb->retrans_lock), iflags ); @@ -382,24 +395,10 @@ void ack_received(struct neighbor *nb, __u32 conn_id, __u32 seqno) first = 1; skb->next->prev = skb->prev; skb->prev->next = skb->next; - - BUG_ON(nb != ps->funcstate.retransmit_queue.nb); - - kfree_skb(skb); - - if (unlikely(unlikely(first) && - unlikely(skb_queue_empty(&(nb->retrans_list))) && - unlikely(nb->retrans_timer_running == 0))) { - mod_timer(&(nb->retrans_timer), jiffies + - msecs_to_jiffies( ((__u32) - atomic_read(&(nb->latency)))/1000)); - nb->retrans_timer_running = 1; - kref_get(&(nb->ref)); - } spin_unlock_irqrestore( &(nb->retrans_lock), iflags ); - - kref_put(&(nb->ref), neighbor_free); + + kref_put(&(ps->funcstate.retransmit_queue.ref), free_skb); } void flush_out(struct conn *rconn) -- 2.11.4.GIT