forked from luck/tmp_suning_uos_patched
Included changes:
- properly release neigh_ifinfo in batadv_iv_ogm_process_per_outif() - properly release orig_ifinfo->router when freeing orig_ifinfo - properly release neigh_node objects during periodic check - properly release neigh_info objects when the related hard_iface is free'd These changes are all very important because they fix some reference counting imbalances that lead to the impossibility of releasing the netdev object used by batman-adv on shutdown. The consequence is that such object cannot be destroyed by the networking stack (the refcounter does not reach zero) thus bringing the system in hanging state during a normal reboot operation or a network reconfiguration. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABCAAGBQJTbyNlAAoJEEKTMo6mOh1VzeUQAJmcP73MMwdFDGfI+3DUD43Z ziaWzHK1/NAkERIJMYu/Nj9BPhFJ/JgYNoYGd4eZ+0IVzIidBKffpGvZYLKJaBBb kVzDt8sHgm7T+bmJdGK5zBCkCrQ66T1/7jF7evzWCtdmzAj9Ld+cJha6sZ6OLY4v WusFFHH2yQgzOGML52HdM99lIfZJu53sdQtYrMI7FpmObwmoBw1VQsmLsJbbFj0A XbFWYNOtQ0s8JvuHPnHB2gsczMXG6AdDuYdG1douOUryjsdg4AsKVWbPWaSuIyS9 ED6TiNsxtRt3A2YDgKrYmcGWHIc7CR4TE97DpdaB1xOEe/h0JPy8NEXaTiXifVi0 yWXaDZAl0J1gEKxda5foqIJZEScQyqWnAGFIIMVsxWxMpv9V3C+XaMgpgC5yQdoQ hgs6lv8U/w7Qevu4oaU2oq64C5ipyzheLuL+l9Ykwig9brJ9pqvBhEr34VDyyLnK l1VVQP5Y94gsPX2FuBaFgQ6oN3xjAkzFWDVKPtdYhMW7l93ER31KWgyJ53zK0Avk wl/h5Xvep7vgA1pvyiu7Lom47QX2SVY3Xt6vsJ42qrR9bp1sLZ+piZaSBPTSuNmo YySwgku6QlQfCFThh09zjuQ8+zwlq5Enjp+fvy/NtzEhTzK1gmknrQo0QF+Fj1Fj 5yz30/XWjUTn1dtBNeBw =GsPT -----END PGP SIGNATURE----- Merge tag 'batman-adv-fix-for-davem' of git://git.open-mesh.org/linux-merge Included changes: - properly release neigh_ifinfo in batadv_iv_ogm_process_per_outif() - properly release orig_ifinfo->router when freeing orig_ifinfo - properly release neigh_node objects during periodic check - properly release neigh_info objects when the related hard_iface is free'd These changes are all very important because they fix some reference counting imbalances that lead to the impossibility of releasing the netdev object used by batman-adv on shutdown. The consequence is that such object cannot be destroyed by the networking stack (the refcounter does not reach zero) thus bringing the system in hanging state during a normal reboot operation or a network reconfiguration.
This commit is contained in:
commit
6262971a8a
@ -1545,6 +1545,8 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
|
||||
if ((orig_neigh_node) && (!is_single_hop_neigh))
|
||||
batadv_orig_node_free_ref(orig_neigh_node);
|
||||
out:
|
||||
if (router_ifinfo)
|
||||
batadv_neigh_ifinfo_free_ref(router_ifinfo);
|
||||
if (router)
|
||||
batadv_neigh_node_free_ref(router);
|
||||
if (router_router)
|
||||
|
@ -501,12 +501,17 @@ batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
|
||||
static void batadv_orig_ifinfo_free_rcu(struct rcu_head *rcu)
|
||||
{
|
||||
struct batadv_orig_ifinfo *orig_ifinfo;
|
||||
struct batadv_neigh_node *router;
|
||||
|
||||
orig_ifinfo = container_of(rcu, struct batadv_orig_ifinfo, rcu);
|
||||
|
||||
if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT)
|
||||
batadv_hardif_free_ref_now(orig_ifinfo->if_outgoing);
|
||||
|
||||
/* this is the last reference to this object */
|
||||
router = rcu_dereference_protected(orig_ifinfo->router, true);
|
||||
if (router)
|
||||
batadv_neigh_node_free_ref_now(router);
|
||||
kfree(orig_ifinfo);
|
||||
}
|
||||
|
||||
@ -701,6 +706,47 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_purge_neigh_ifinfo - purge obsolete ifinfo entries from neighbor
|
||||
* @bat_priv: the bat priv with all the soft interface information
|
||||
* @neigh: orig node which is to be checked
|
||||
*/
|
||||
static void
|
||||
batadv_purge_neigh_ifinfo(struct batadv_priv *bat_priv,
|
||||
struct batadv_neigh_node *neigh)
|
||||
{
|
||||
struct batadv_neigh_ifinfo *neigh_ifinfo;
|
||||
struct batadv_hard_iface *if_outgoing;
|
||||
struct hlist_node *node_tmp;
|
||||
|
||||
spin_lock_bh(&neigh->ifinfo_lock);
|
||||
|
||||
/* for all ifinfo objects for this neighinator */
|
||||
hlist_for_each_entry_safe(neigh_ifinfo, node_tmp,
|
||||
&neigh->ifinfo_list, list) {
|
||||
if_outgoing = neigh_ifinfo->if_outgoing;
|
||||
|
||||
/* always keep the default interface */
|
||||
if (if_outgoing == BATADV_IF_DEFAULT)
|
||||
continue;
|
||||
|
||||
/* don't purge if the interface is not (going) down */
|
||||
if ((if_outgoing->if_status != BATADV_IF_INACTIVE) &&
|
||||
(if_outgoing->if_status != BATADV_IF_NOT_IN_USE) &&
|
||||
(if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED))
|
||||
continue;
|
||||
|
||||
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
||||
"neighbor/ifinfo purge: neighbor %pM, iface: %s\n",
|
||||
neigh->addr, if_outgoing->net_dev->name);
|
||||
|
||||
hlist_del_rcu(&neigh_ifinfo->list);
|
||||
batadv_neigh_ifinfo_free_ref(neigh_ifinfo);
|
||||
}
|
||||
|
||||
spin_unlock_bh(&neigh->ifinfo_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_purge_orig_ifinfo - purge obsolete ifinfo entries from originator
|
||||
* @bat_priv: the bat priv with all the soft interface information
|
||||
@ -800,6 +846,11 @@ batadv_purge_orig_neighbors(struct batadv_priv *bat_priv,
|
||||
|
||||
hlist_del_rcu(&neigh_node->list);
|
||||
batadv_neigh_node_free_ref(neigh_node);
|
||||
} else {
|
||||
/* only necessary if not the whole neighbor is to be
|
||||
* deleted, but some interface has been removed.
|
||||
*/
|
||||
batadv_purge_neigh_ifinfo(bat_priv, neigh_node);
|
||||
}
|
||||
}
|
||||
|
||||
@ -857,7 +908,7 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
|
||||
{
|
||||
struct batadv_neigh_node *best_neigh_node;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
bool changed;
|
||||
bool changed_ifinfo, changed_neigh;
|
||||
|
||||
if (batadv_has_timed_out(orig_node->last_seen,
|
||||
2 * BATADV_PURGE_TIMEOUT)) {
|
||||
@ -867,10 +918,10 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
|
||||
jiffies_to_msecs(orig_node->last_seen));
|
||||
return true;
|
||||
}
|
||||
changed = batadv_purge_orig_ifinfo(bat_priv, orig_node);
|
||||
changed = changed || batadv_purge_orig_neighbors(bat_priv, orig_node);
|
||||
changed_ifinfo = batadv_purge_orig_ifinfo(bat_priv, orig_node);
|
||||
changed_neigh = batadv_purge_orig_neighbors(bat_priv, orig_node);
|
||||
|
||||
if (!changed)
|
||||
if (!changed_ifinfo && !changed_neigh)
|
||||
return false;
|
||||
|
||||
/* first for NULL ... */
|
||||
|
Loading…
Reference in New Issue
Block a user