Message ID | 1441122196-11662-11-git-send-email-ahmed@gandi.net |
---|---|
State | RFC, archived |
Delegated to: | David Miller |
Headers | show |
On 09/01/2015 06:43 PM, Ahmed Amamou wrote: > rbr_node are used to save distant Rbridges information > they are use by local Rbridge to take routing decision > this patch add get/put/free/find/del function to rbr_node to > avoid freeing a rbr_node that is still in use for routing > > Signed-off-by: Ahmed Amamou <ahmed@gandi.net> > Signed-off-by: Kamel Haddadou <kamel@gandi.net> > Signed-off-by: William Dauchy <william@gandi.net> > --- > net/bridge/rbr.c | 35 +++++++++++++++++++++++++++++++++++ > net/bridge/rbr_private.h | 23 +++++++++++++++++++++++ > 2 files changed, 58 insertions(+) [...] > diff --git a/net/bridge/rbr_private.h b/net/bridge/rbr_private.h > index 9166a8b..186e454 100644 > --- a/net/bridge/rbr_private.h > +++ b/net/bridge/rbr_private.h > @@ -44,7 +44,30 @@ struct rbr { [...] > +static inline void rbr_node_put(struct rbr_node *rbr_node) > +{ > + if (rbr_node) { > + if (unlikely(atomic_dec_and_test(&rbr_node->refs))) Could fold both 'if's into one and avoid {} altogether. > + rbr_node_free(rbr_node); > + } > +} > + MBR, Sergei -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/net/bridge/rbr.c b/net/bridge/rbr.c index 31e72ef..718deb3 100644 --- a/net/bridge/rbr.c +++ b/net/bridge/rbr.c @@ -83,3 +83,38 @@ int set_treeroot(struct rbr *rbr, uint16_t treeroot) set_tree_root_fail: return -ENOENT; } + +struct rbr_node *rbr_find_node(struct rbr *rbr, __u16 nickname) +{ + struct rbr_node *rbr_node; + + if (unlikely(!VALID_NICK(nickname))) + return NULL; + rbr_node = rcu_dereference(rbr->rbr_nodes[nickname]); + rbr_node_get(rbr_node); + + return rbr_node; +} + +static void rbr_del_node(struct rbr *rbr, uint16_t nickname) +{ + struct rbr_node *rbr_node; + + if (likely(VALID_NICK(nickname))) { + rbr_node = rbr->rbr_nodes[nickname]; + if (likely(rbr_node)) { + rcu_assign_pointer(rbr->rbr_nodes[nickname], NULL); + rbr_node_put(rbr_node); + } + } +} + +static void rbr_del_all(struct rbr *rbr) +{ + unsigned int i; + + for (i = RBRIDGE_NICKNAME_MIN; i < RBRIDGE_NICKNAME_MAX; i++) { + if (likely(rbr->rbr_nodes[i])) + rbr_del_node(rbr, i); + } +} diff --git a/net/bridge/rbr_private.h b/net/bridge/rbr_private.h index 9166a8b..186e454 100644 --- a/net/bridge/rbr_private.h +++ b/net/bridge/rbr_private.h @@ -44,7 +44,30 @@ struct rbr { struct net_bridge *br; /* back pointer */ }; +static inline void rbr_node_free(struct rbr_node *rbr_node) +{ + if (likely(rbr_node)) { + kfree(rbr_node->rbr_ni); + kfree(rbr_node); + } +} + +static inline void rbr_node_get(struct rbr_node *rbr_node) +{ + if (likely(rbr_node)) + atomic_inc(&rbr_node->refs); +} + +static inline void rbr_node_put(struct rbr_node *rbr_node) +{ + if (rbr_node) { + if (unlikely(atomic_dec_and_test(&rbr_node->refs))) + rbr_node_free(rbr_node); + } +} + int set_treeroot(struct rbr *rbr, uint16_t treeroot); +struct rbr_node *rbr_find_node(struct rbr *rbr, __u16 nickname); /* Access the adjacency nick list at the end of rbr_nickinfo */ #define RBR_NI_ADJNICKSPTR(v) ((u16 *)((struct rbr_nickinfo *)(v) + 1))