From d0a30da80bcdc4f478cee754cdb83e7fdb4cbc23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20L=C3=BCssing?= Date: Mon, 15 Apr 2013 21:43:29 +0800 Subject: [PATCH] --- yaml --- r: 376108 b: refs/heads/master c: 72822225bd41320a98f5d7cde38317766e18983f h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/net/batman-adv/originator.c | 16 ++++++++++++++++ trunk/net/batman-adv/originator.h | 1 + trunk/net/batman-adv/translation-table.c | 7 ++++++- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index 37c07f11727c..96742505cabf 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: b0ce3508b25ea6fa10ae3ca254de1d695b521702 +refs/heads/master: 72822225bd41320a98f5d7cde38317766e18983f diff --git a/trunk/net/batman-adv/originator.c b/trunk/net/batman-adv/originator.c index 2f3452546636..fad1a2093e15 100644 --- a/trunk/net/batman-adv/originator.c +++ b/trunk/net/batman-adv/originator.c @@ -156,12 +156,28 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu) kfree(orig_node); } +/** + * batadv_orig_node_free_ref - decrement the orig node refcounter and possibly + * schedule an rcu callback for freeing it + * @orig_node: the orig node to free + */ void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node) { if (atomic_dec_and_test(&orig_node->refcount)) call_rcu(&orig_node->rcu, batadv_orig_node_free_rcu); } +/** + * batadv_orig_node_free_ref_now - decrement the orig node refcounter and + * possibly free it (without rcu callback) + * @orig_node: the orig node to free + */ +void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node) +{ + if (atomic_dec_and_test(&orig_node->refcount)) + batadv_orig_node_free_rcu(&orig_node->rcu); +} + void batadv_originator_free(struct batadv_priv *bat_priv) { struct batadv_hashtable *hash = bat_priv->orig_hash; diff --git a/trunk/net/batman-adv/originator.h b/trunk/net/batman-adv/originator.h index 7df48fa7669d..734e5a3d8a5b 100644 --- a/trunk/net/batman-adv/originator.h +++ b/trunk/net/batman-adv/originator.h @@ -26,6 +26,7 @@ int batadv_originator_init(struct batadv_priv *bat_priv); void batadv_originator_free(struct batadv_priv *bat_priv); void batadv_purge_orig_ref(struct batadv_priv *bat_priv); void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node); +void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node); struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv, const uint8_t *addr); struct batadv_neigh_node * diff --git a/trunk/net/batman-adv/translation-table.c b/trunk/net/batman-adv/translation-table.c index 5e89deeb9542..9e8748575845 100644 --- a/trunk/net/batman-adv/translation-table.c +++ b/trunk/net/batman-adv/translation-table.c @@ -144,7 +144,12 @@ static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu) struct batadv_tt_orig_list_entry *orig_entry; orig_entry = container_of(rcu, struct batadv_tt_orig_list_entry, rcu); - batadv_orig_node_free_ref(orig_entry->orig_node); + + /* We are in an rcu callback here, therefore we cannot use + * batadv_orig_node_free_ref() and its call_rcu(): + * An rcu_barrier() wouldn't wait for that to finish + */ + batadv_orig_node_free_ref_now(orig_entry->orig_node); kfree(orig_entry); }