The following commit has been merged in the merge/master branch: commit e9d8868215fdb4c61a3440bbcbb34c50e546e6e2 Merge: 3515604d82d5b8f80201d8ff0cc4708da8cddb00 7d2f8a773bae5e07cadc9a9f74ac21abe32cde13 Author: Marek Lindner mareklindner@neomailbox.ch Date: Sun Mar 20 17:57:20 2016 +0800
Merge branch 'maint' into next
diff --combined net/batman-adv/soft-interface.c index 0710379,64d721c..8a136b6 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@@ -1,4 -1,4 +1,4 @@@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * @@@ -30,7 -30,6 +30,7 @@@ #include <linux/if_vlan.h> #include <linux/jiffies.h> #include <linux/kernel.h> +#include <linux/kref.h> #include <linux/list.h> #include <linux/lockdep.h> #include <linux/netdevice.h> @@@ -377,7 -376,7 +377,7 @@@ dropped_freed batadv_inc_counter(bat_priv, BATADV_CNT_TX_DROPPED); end: if (primary_if) - batadv_hardif_free_ref(primary_if); + batadv_hardif_put(primary_if); return NETDEV_TX_OK; }
@@@ -408,11 -407,17 +408,17 @@@ void batadv_interface_rx(struct net_dev */ nf_reset(skb);
+ if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) + goto dropped; + vid = batadv_get_vid(skb, 0); ethhdr = eth_hdr(skb);
switch (ntohs(ethhdr->h_proto)) { case ETH_P_8021Q: + if (!pskb_may_pull(skb, VLAN_ETH_HLEN)) + goto dropped; + vhdr = (struct vlan_ethhdr *)skb->data;
if (vhdr->h_vlan_encapsulated_proto != ethertype) @@@ -424,8 -429,6 +430,6 @@@ }
/* skb->dev & skb->pkt_type are set here */ - if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) - goto dropped; skb->protocol = eth_type_trans(skb, soft_iface);
/* should not be necessary anymore as we use skb_pull_rcsum() @@@ -479,34 -482,22 +483,34 @@@ out }
/** - * batadv_softif_vlan_free_ref - decrease the vlan object refcounter and - * possibly free it + * batadv_softif_vlan_release - release vlan from lists and queue for free after + * rcu grace period + * @ref: kref pointer of the vlan object + */ +static void batadv_softif_vlan_release(struct kref *ref) +{ + struct batadv_softif_vlan *vlan; + + vlan = container_of(ref, struct batadv_softif_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); +} + +/** + * batadv_softif_vlan_put - decrease the vlan object refcounter and + * possibly release it * @vlan: the vlan object to release */ -void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan) +void batadv_softif_vlan_put(struct batadv_softif_vlan *vlan) { if (!vlan) return;
- 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); - } + kref_put(&vlan->refcount, batadv_softif_vlan_release); }
/** @@@ -527,7 -518,7 +531,7 @@@ struct batadv_softif_vlan *batadv_softi if (vlan_tmp->vid != vid) continue;
- if (!atomic_inc_not_zero(&vlan_tmp->refcount)) + if (!kref_get_unless_zero(&vlan_tmp->refcount)) continue;
vlan = vlan_tmp; @@@ -552,7 -543,7 +556,7 @@@ int batadv_softif_create_vlan(struct ba
vlan = batadv_softif_vlan_get(bat_priv, vid); if (vlan) { - batadv_softif_vlan_free_ref(vlan); + batadv_softif_vlan_put(vlan); return -EEXIST; }
@@@ -562,7 -553,7 +566,7 @@@
vlan->bat_priv = bat_priv; vlan->vid = vid; - atomic_set(&vlan->refcount, 1); + kref_init(&vlan->refcount);
atomic_set(&vlan->ap_isolation, 0);
@@@ -601,7 -592,7 +605,7 @@@ static void batadv_softif_destroy_vlan( vlan->vid, "vlan interface destroyed", false);
batadv_sysfs_del_vlan(bat_priv, vlan); - batadv_softif_vlan_free_ref(vlan); + batadv_softif_vlan_put(vlan); }
/** @@@ -646,7 -637,7 +650,7 @@@ static int batadv_interface_add_vid(str if (!vlan->kobj) { ret = batadv_sysfs_add_vlan(bat_priv->soft_iface, vlan); if (ret) { - batadv_softif_vlan_free_ref(vlan); + batadv_softif_vlan_put(vlan); return ret; } } @@@ -693,7 -684,7 +697,7 @@@ static int batadv_interface_kill_vid(st batadv_softif_destroy_vlan(bat_priv, vlan);
/* finally free the vlan object */ - batadv_softif_vlan_free_ref(vlan); + batadv_softif_vlan_put(vlan);
return 0; } @@@ -749,7 -740,7 +753,7 @@@ static void batadv_softif_destroy_finis vlan = batadv_softif_vlan_get(bat_priv, BATADV_NO_FLAGS); if (vlan) { batadv_softif_destroy_vlan(bat_priv, vlan); - batadv_softif_vlan_free_ref(vlan); + batadv_softif_vlan_put(vlan); }
batadv_sysfs_del_meshif(soft_iface); @@@ -878,7 -869,7 +882,7 @@@ static int batadv_softif_slave_add(stru
out: if (hard_iface) - batadv_hardif_free_ref(hard_iface); + batadv_hardif_put(hard_iface); return ret; }
@@@ -905,7 -896,7 +909,7 @@@ static int batadv_softif_slave_del(stru
out: if (hard_iface) - batadv_hardif_free_ref(hard_iface); + batadv_hardif_put(hard_iface); return ret; }