From patchwork Sun Mar 17 04:44:57 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Linus_L=C3=BCssing?= X-Patchwork-Id: 2809 Return-Path: Received: from mout.web.de (mout.web.de [212.227.15.4]) by open-mesh.org (Postfix) with ESMTP id 27CC0600758 for ; Sun, 17 Mar 2013 05:45:06 +0100 (CET) Received: from localhost ([95.211.13.35]) by smtp.web.de (mrweb002) with ESMTPSA (Nemesis) id 0MMFFF-1UMKGC2BSv-007pLO; Sun, 17 Mar 2013 05:45:05 +0100 From: =?UTF-8?q?Linus=20L=C3=BCssing?= To: b.a.t.m.a.n@lists.open-mesh.org Date: Sun, 17 Mar 2013 05:44:57 +0100 Message-Id: <1363495498-17830-1-git-send-email-linus.luessing@web.de> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: References: MIME-Version: 1.0 X-Provags-ID: V02:K0:yM5lrgJMseY6fKy3WJpefPAh2mP2Go4BA0BXn4SiXCE k0qHYIa3szPZjQTKJOVPCDkh6roRBjy8xSx5cLQ+LAGbl9IsO5 FqYQhFxH01W7HPlkNDU2WNAm6XT7ULYWIQzbYW5RFCrGJFC6Oe lxShs8FeRuRVJTdCEyDpSE2jb7RD1gfxnk9mZDgrgnaPCk+TZT iszX0GPwyI6G9ChVgaZ2Q== Subject: [B.A.T.M.A.N.] [PATCH 1/2] batman-adv: Fix rcu_barrier() miss due to double call_rcu() in TT code X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.15 Precedence: list Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 17 Mar 2013 04:45:06 -0000 rcu_barrier() only waits for the currently scheduled rcu functions to finish - it won't wait for any function scheduled via another call_rcu() within an rcu scheduled function. Unfortunately our batadv_tt_orig_list_entry_free_ref() does just that, via a batadv_orig_node_free_ref() call, leading to our rcu_barrier() call potentially missing such a batadv_orig_node_free_ref(). This patch fixes this issue by calling the batadv_orig_node_free_rcu() directly from the rcu callback, removing the unnecessary, additional call_rcu() layer here. Signed-off-by: Linus Lüssing diff --git a/originator.c b/originator.c index 585e684..013c7d0 100644 --- a/originator.c +++ b/originator.c @@ -117,7 +117,7 @@ out: return neigh_node; } -static void batadv_orig_node_free_rcu(struct rcu_head *rcu) +void batadv_orig_node_free_rcu(struct rcu_head *rcu) { struct hlist_node *node_tmp; struct batadv_neigh_node *neigh_node, *tmp_neigh_node; diff --git a/originator.h b/originator.h index 7df48fa..4f9f88b 100644 --- a/originator.h +++ b/originator.h @@ -25,6 +25,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_rcu(struct rcu_head *rcu); void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node); struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv, const uint8_t *addr); diff --git a/translation-table.c b/translation-table.c index 9322320..ee91cc1 100644 --- a/translation-table.c +++ b/translation-table.c @@ -144,7 +144,10 @@ 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); + + if (atomic_dec_and_test(&orig_entry->orig_node->refcount)) + batadv_orig_node_free_rcu(&orig_entry->orig_node->rcu); + kfree(orig_entry); }