The following commit has been merged in the merge/master branch: commit 0a1689da7bfc32d9f6caa581af41b560fd1e164f Merge: ac44ee35fb889d6348f5b51cc832d906810c2453 a1b142620c8dad5e75fbb615925fb76846b5d45d Author: Antonio Quartulli antonio@meshcoding.com Date: Thu May 15 19:14:55 2014 +0200
Merge commit 'a1b142620c8dad5e75fbb615925fb76846b5d45d' into merge/master
diff --combined net/batman-adv/originator.c index bb1425f,6a48451..6a48451 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@@ -709,7 -709,7 +709,7 @@@ free_orig_node /** * batadv_purge_neigh_ifinfo - purge obsolete ifinfo entries from neighbor * @bat_priv: the bat priv with all the soft interface information - * @neigh_node: orig node which is to be checked + * @neigh: orig node which is to be checked */ static void batadv_purge_neigh_ifinfo(struct batadv_priv *bat_priv, @@@ -847,8 -847,8 +847,8 @@@ batadv_purge_orig_neighbors(struct bata hlist_del_rcu(&neigh_node->list); batadv_neigh_node_free_ref(neigh_node); } else { - /* only neccesary if not the whole neighbor is to be deleted, - * but some interface has been removed. + /* 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); } diff --combined net/batman-adv/soft-interface.c index 9f070de,a827921..a827921 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@@ -454,10 -454,15 +454,15 @@@ out * possibly free it * @softif_vlan: the vlan object to release */ - void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *softif_vlan) + void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan) { - if (atomic_dec_and_test(&softif_vlan->refcount)) - kfree_rcu(softif_vlan, rcu); + if (atomic_dec_and_test(&vlan->refcount)) { + spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock); + hlist_del_rcu(&vlan->list); + spin_unlock_bh(&vlan->bat_priv->softif_vlan_list_lock); + + kfree_rcu(vlan, rcu); + } }
/** @@@ -511,6 -516,7 +516,7 @@@ int batadv_softif_create_vlan(struct ba if (!vlan) return -ENOMEM;
+ vlan->bat_priv = bat_priv; vlan->vid = vid; atomic_set(&vlan->refcount, 1);
@@@ -522,6 -528,10 +528,10 @@@ return err; }
+ spin_lock_bh(&bat_priv->softif_vlan_list_lock); + hlist_add_head_rcu(&vlan->list, &bat_priv->softif_vlan_list); + spin_unlock_bh(&bat_priv->softif_vlan_list_lock); + /* add a new TT local entry. This one will be marked with the NOPURGE * flag */ @@@ -529,10 -539,6 +539,6 @@@ bat_priv->soft_iface->dev_addr, vid, BATADV_NULL_IFINDEX, BATADV_NO_MARK);
- spin_lock_bh(&bat_priv->softif_vlan_list_lock); - hlist_add_head_rcu(&vlan->list, &bat_priv->softif_vlan_list); - spin_unlock_bh(&bat_priv->softif_vlan_list_lock); - return 0; }
@@@ -544,18 -550,13 +550,13 @@@ static void batadv_softif_destroy_vlan(struct batadv_priv *bat_priv, struct batadv_softif_vlan *vlan) { - spin_lock_bh(&bat_priv->softif_vlan_list_lock); - hlist_del_rcu(&vlan->list); - spin_unlock_bh(&bat_priv->softif_vlan_list_lock); - - batadv_sysfs_del_vlan(bat_priv, vlan); - /* explicitly remove the associated TT local entry because it is marked * with the NOPURGE flag */ batadv_tt_local_remove(bat_priv, bat_priv->soft_iface->dev_addr, vlan->vid, "vlan interface destroyed", false);
+ batadv_sysfs_del_vlan(bat_priv, vlan); batadv_softif_vlan_free_ref(vlan); }
@@@ -573,6 -574,8 +574,8 @@@ static int batadv_interface_add_vid(str unsigned short vid) { struct batadv_priv *bat_priv = netdev_priv(dev); + struct batadv_softif_vlan *vlan; + int ret;
/* only 802.1Q vlans are supported. * batman-adv does not know how to handle other types @@@ -582,7 -585,36 +585,36 @@@
vid |= BATADV_VLAN_HAS_TAG;
- return batadv_softif_create_vlan(bat_priv, vid); + /* if a new vlan is getting created and it already exists, it means that + * it was not deleted yet. batadv_softif_vlan_get() increases the + * refcount in order to revive the object. + * + * if it does not exist then create it. + */ + vlan = batadv_softif_vlan_get(bat_priv, vid); + if (!vlan) + return batadv_softif_create_vlan(bat_priv, vid); + + /* recreate the sysfs object if it was already destroyed (and it should + * be since we received a kill_vid() for this vlan + */ + if (!vlan->kobj) { + ret = batadv_sysfs_add_vlan(bat_priv->soft_iface, vlan); + if (ret) { + batadv_softif_vlan_free_ref(vlan); + return ret; + } + } + + /* add a new TT local entry. This one will be marked with the NOPURGE + * flag. This must be added again, even if the vlan object already + * exists, because the entry was deleted by kill_vid() + */ + batadv_tt_local_add(bat_priv->soft_iface, + bat_priv->soft_iface->dev_addr, vid, + BATADV_NULL_IFINDEX, BATADV_NO_MARK); + + return 0; }
/** diff --combined net/batman-adv/translation-table.c index d636bde,5f59e7f..5f59e7f --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@@ -511,6 -511,7 +511,7 @@@ bool batadv_tt_local_add(struct net_dev struct batadv_priv *bat_priv = netdev_priv(soft_iface); struct batadv_tt_local_entry *tt_local; struct batadv_tt_global_entry *tt_global = NULL; + struct batadv_softif_vlan *vlan; struct net_device *in_dev = NULL; struct hlist_head *head; struct batadv_tt_orig_list_entry *orig_entry; @@@ -572,6 -573,9 +573,9 @@@ if (!tt_local) goto out;
+ /* increase the refcounter of the related vlan */ + vlan = batadv_softif_vlan_get(bat_priv, vid); + batadv_dbg(BATADV_DBG_TT, bat_priv, "Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n", addr, BATADV_PRINT_VID(vid), @@@ -604,6 -608,7 +608,7 @@@ if (unlikely(hash_added != 0)) { /* remove the reference for the hash */ batadv_tt_local_entry_free_ref(tt_local); + batadv_softif_vlan_free_ref(vlan); goto out; }
@@@ -1009,6 -1014,7 +1014,7 @@@ uint16_t batadv_tt_local_remove(struct { struct batadv_tt_local_entry *tt_local_entry; uint16_t flags, curr_flags = BATADV_NO_FLAGS; + struct batadv_softif_vlan *vlan;
tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid); if (!tt_local_entry) @@@ -1039,6 -1045,11 +1045,11 @@@ hlist_del_rcu(&tt_local_entry->common.hash_entry); batadv_tt_local_entry_free_ref(tt_local_entry);
+ /* decrease the reference held for this vlan */ + vlan = batadv_softif_vlan_get(bat_priv, vid); + batadv_softif_vlan_free_ref(vlan); + batadv_softif_vlan_free_ref(vlan); + out: if (tt_local_entry) batadv_tt_local_entry_free_ref(tt_local_entry); @@@ -1111,6 -1122,7 +1122,7 @@@ static void batadv_tt_local_table_free( spinlock_t *list_lock; /* protects write access to the hash lists */ struct batadv_tt_common_entry *tt_common_entry; struct batadv_tt_local_entry *tt_local; + struct batadv_softif_vlan *vlan; struct hlist_node *node_tmp; struct hlist_head *head; uint32_t i; @@@ -1131,6 -1143,13 +1143,13 @@@ tt_local = container_of(tt_common_entry, struct batadv_tt_local_entry, common); + + /* decrease the reference held for this vlan */ + vlan = batadv_softif_vlan_get(bat_priv, + tt_common_entry->vid); + batadv_softif_vlan_free_ref(vlan); + batadv_softif_vlan_free_ref(vlan); + batadv_tt_local_entry_free_ref(tt_local); } spin_unlock_bh(list_lock); @@@ -3139,6 -3158,7 +3158,7 @@@ static void batadv_tt_local_purge_pendi struct batadv_hashtable *hash = bat_priv->tt.local_hash; struct batadv_tt_common_entry *tt_common; struct batadv_tt_local_entry *tt_local; + struct batadv_softif_vlan *vlan; struct hlist_node *node_tmp; struct hlist_head *head; spinlock_t *list_lock; /* protects write access to the hash lists */ @@@ -3167,6 -3187,12 +3187,12 @@@ tt_local = container_of(tt_common, struct batadv_tt_local_entry, common); + + /* decrease the reference held for this vlan */ + vlan = batadv_softif_vlan_get(bat_priv, tt_common->vid); + batadv_softif_vlan_free_ref(vlan); + batadv_softif_vlan_free_ref(vlan); + batadv_tt_local_entry_free_ref(tt_local); } spin_unlock_bh(list_lock); diff --combined net/batman-adv/types.h index 34891a5,8854c05..8854c05 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@@ -687,6 -687,7 +687,7 @@@ struct batadv_priv_nc
/** * struct batadv_softif_vlan - per VLAN attributes set + * @bat_priv: pointer to the mesh object * @vid: VLAN identifier * @kobj: kobject for sysfs vlan subdirectory * @ap_isolation: AP isolation state @@@ -696,6 -697,7 +697,7 @@@ * @rcu: struct used for freeing in a RCU-safe manner */ struct batadv_softif_vlan { + struct batadv_priv *bat_priv; unsigned short vid; struct kobject *kobj; atomic_t ap_isolation; /* boolean */