aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorAntonio Quartulli2013-05-07 01:06:18 +0200
committerAntonio Quartulli2013-05-09 12:39:45 +0200
commita4361860351e87876aebd9595906d928ce8572c6 (patch)
tree4a9e979287905c7c94d9229640870af0b8d853bc /net
parent88e48d7b3340ef07b108eb8a8b3813dd093cc7f7 (diff)
batman-adv: reorder clean up routine in order to avoid race conditions
nc_worker accesses the originator table during its periodic work, but since the originator table is freed before stopping the worker this leads to a global protection fault. Fix this by killing the worker (in nc_free) before freeing the originator table. Moreover tidy up the entire clean up routine by running all the subcomponents freeing procedures first and then killing the TT and the originator tables at the end. Signed-off-by: Antonio Quartulli <ordex@autistici.org> Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Diffstat (limited to 'net')
-rw-r--r--net/batman-adv/main.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 9c620cd3b5f7..1240f07ad31d 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -163,14 +163,22 @@ void batadv_mesh_free(struct net_device *soft_iface)
batadv_vis_quit(bat_priv);
batadv_gw_node_purge(bat_priv);
- batadv_originator_free(bat_priv);
batadv_nc_free(bat_priv);
+ batadv_dat_free(bat_priv);
+ batadv_bla_free(bat_priv);
+ /* Free the TT and the originator tables only after having terminated
+ * all the other depending components which may use these structures for
+ * their purposes.
+ */
batadv_tt_free(bat_priv);
- batadv_bla_free(bat_priv);
-
- batadv_dat_free(bat_priv);
+ /* Since the originator table clean up routine is accessing the TT
+ * tables as well, it has to be invoked after the TT tables have been
+ * freed and marked as empty. This ensures that no cleanup RCU callbacks
+ * accessing the TT data are scheduled for later execution.
+ */
+ batadv_originator_free(bat_priv);
free_percpu(bat_priv->bat_counters);