|
|
@@ -574,15 +574,20 @@ int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
|
|
|
struct batadv_softif_vlan *vlan;
|
|
|
int err;
|
|
|
|
|
|
+ spin_lock_bh(&bat_priv->softif_vlan_list_lock);
|
|
|
+
|
|
|
vlan = batadv_softif_vlan_get(bat_priv, vid);
|
|
|
if (vlan) {
|
|
|
batadv_softif_vlan_put(vlan);
|
|
|
+ spin_unlock_bh(&bat_priv->softif_vlan_list_lock);
|
|
|
return -EEXIST;
|
|
|
}
|
|
|
|
|
|
vlan = kzalloc(sizeof(*vlan), GFP_ATOMIC);
|
|
|
- if (!vlan)
|
|
|
+ if (!vlan) {
|
|
|
+ spin_unlock_bh(&bat_priv->softif_vlan_list_lock);
|
|
|
return -ENOMEM;
|
|
|
+ }
|
|
|
|
|
|
vlan->bat_priv = bat_priv;
|
|
|
vlan->vid = vid;
|
|
|
@@ -590,17 +595,23 @@ int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
|
|
|
|
|
|
atomic_set(&vlan->ap_isolation, 0);
|
|
|
|
|
|
+ kref_get(&vlan->refcount);
|
|
|
+ hlist_add_head_rcu(&vlan->list, &bat_priv->softif_vlan_list);
|
|
|
+ spin_unlock_bh(&bat_priv->softif_vlan_list_lock);
|
|
|
+
|
|
|
+ /* batadv_sysfs_add_vlan cannot be in the spinlock section due to the
|
|
|
+ * sleeping behavior of the sysfs functions and the fs_reclaim lock
|
|
|
+ */
|
|
|
err = batadv_sysfs_add_vlan(bat_priv->soft_iface, vlan);
|
|
|
if (err) {
|
|
|
- kfree(vlan);
|
|
|
+ /* ref for the function */
|
|
|
+ batadv_softif_vlan_put(vlan);
|
|
|
+
|
|
|
+ /* ref for the list */
|
|
|
+ batadv_softif_vlan_put(vlan);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
- spin_lock_bh(&bat_priv->softif_vlan_list_lock);
|
|
|
- kref_get(&vlan->refcount);
|
|
|
- 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
|
|
|
*/
|