[linux-next] LinuxNextTracking branch, master, updated. next-20110624

batman at open-mesh.org batman at open-mesh.org
Fri Jun 24 16:09:23 CEST 2011


The following commit has been merged in the master branch:
commit 9c6bc16577171100e5efab0ea09ebf5884822ed6
Merge: 03746b0a02d25866a29cd8d7306d221c238d6397 af20b710479ae662829cf739b521390daa7fcbcb
Author: David S. Miller <davem at davemloft.net>
Date:   Sun Apr 17 17:37:29 2011 -0700

    Merge branch 'batman-adv/next' of git://git.open-mesh.org/ecsv/linux-merge

diff --combined net/batman-adv/soft-interface.c
index 824e1f6,58ce440..1f6f756
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@@ -90,10 -90,51 +90,51 @@@ static void softif_neigh_free_ref(struc
  		call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu);
  }
  
+ static struct softif_neigh *softif_neigh_get_selected(struct bat_priv *bat_priv)
+ {
+ 	struct softif_neigh *neigh;
+ 
+ 	rcu_read_lock();
+ 	neigh = rcu_dereference(bat_priv->softif_neigh);
+ 
+ 	if (neigh && !atomic_inc_not_zero(&neigh->refcount))
+ 		neigh = NULL;
+ 
+ 	rcu_read_unlock();
+ 	return neigh;
+ }
+ 
+ static void softif_neigh_select(struct bat_priv *bat_priv,
+ 				struct softif_neigh *new_neigh)
+ {
+ 	struct softif_neigh *curr_neigh;
+ 
+ 	spin_lock_bh(&bat_priv->softif_neigh_lock);
+ 
+ 	if (new_neigh && !atomic_inc_not_zero(&new_neigh->refcount))
+ 		new_neigh = NULL;
+ 
+ 	curr_neigh = bat_priv->softif_neigh;
+ 	rcu_assign_pointer(bat_priv->softif_neigh, new_neigh);
+ 
+ 	if (curr_neigh)
+ 		softif_neigh_free_ref(curr_neigh);
+ 
+ 	spin_unlock_bh(&bat_priv->softif_neigh_lock);
+ }
+ 
+ static void softif_neigh_deselect(struct bat_priv *bat_priv)
+ {
+ 	softif_neigh_select(bat_priv, NULL);
+ }
+ 
  void softif_neigh_purge(struct bat_priv *bat_priv)
  {
- 	struct softif_neigh *softif_neigh, *softif_neigh_tmp;
+ 	struct softif_neigh *softif_neigh, *curr_softif_neigh;
  	struct hlist_node *node, *node_tmp;
+ 	char do_deselect = 0;
+ 
+ 	curr_softif_neigh = softif_neigh_get_selected(bat_priv);
  
  	spin_lock_bh(&bat_priv->softif_neigh_lock);
  
@@@ -105,22 -146,26 +146,26 @@@
  		    (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE))
  			continue;
  
- 		hlist_del_rcu(&softif_neigh->list);
- 
- 		if (bat_priv->softif_neigh == softif_neigh) {
+ 		if (curr_softif_neigh == softif_neigh) {
  			bat_dbg(DBG_ROUTES, bat_priv,
  				 "Current mesh exit point '%pM' vanished "
  				 "(vid: %d).\n",
  				 softif_neigh->addr, softif_neigh->vid);
- 			softif_neigh_tmp = bat_priv->softif_neigh;
- 			bat_priv->softif_neigh = NULL;
- 			softif_neigh_free_ref(softif_neigh_tmp);
+ 			do_deselect = 1;
  		}
  
+ 		hlist_del_rcu(&softif_neigh->list);
  		softif_neigh_free_ref(softif_neigh);
  	}
  
  	spin_unlock_bh(&bat_priv->softif_neigh_lock);
+ 
+ 	/* soft_neigh_deselect() needs to acquire the softif_neigh_lock */
+ 	if (do_deselect)
+ 		softif_neigh_deselect(bat_priv);
+ 
+ 	if (curr_softif_neigh)
+ 		softif_neigh_free_ref(curr_softif_neigh);
  }
  
  static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
@@@ -171,6 -216,7 +216,7 @@@ int softif_neigh_seq_print_text(struct 
  	struct bat_priv *bat_priv = netdev_priv(net_dev);
  	struct softif_neigh *softif_neigh;
  	struct hlist_node *node;
+ 	struct softif_neigh *curr_softif_neigh;
  
  	if (!bat_priv->primary_if) {
  		return seq_printf(seq, "BATMAN mesh %s disabled - "
@@@ -180,14 -226,17 +226,17 @@@
  
  	seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name);
  
+ 	curr_softif_neigh = softif_neigh_get_selected(bat_priv);
  	rcu_read_lock();
  	hlist_for_each_entry_rcu(softif_neigh, node,
  				 &bat_priv->softif_neigh_list, list)
  		seq_printf(seq, "%s %pM (vid: %d)\n",
- 				bat_priv->softif_neigh == softif_neigh
+ 				curr_softif_neigh == softif_neigh
  				? "=>" : "  ", softif_neigh->addr,
  				softif_neigh->vid);
  	rcu_read_unlock();
+ 	if (curr_softif_neigh)
+ 		softif_neigh_free_ref(curr_softif_neigh);
  
  	return 0;
  }
@@@ -198,7 -247,8 +247,8 @@@ static void softif_batman_recv(struct s
  	struct bat_priv *bat_priv = netdev_priv(dev);
  	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
  	struct batman_packet *batman_packet;
- 	struct softif_neigh *softif_neigh, *softif_neigh_tmp;
+ 	struct softif_neigh *softif_neigh;
+ 	struct softif_neigh *curr_softif_neigh = NULL;
  
  	if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
  		batman_packet = (struct batman_packet *)
@@@ -223,7 -273,8 +273,8 @@@
  	if (!softif_neigh)
  		goto err;
  
- 	if (bat_priv->softif_neigh == softif_neigh)
+ 	curr_softif_neigh = softif_neigh_get_selected(bat_priv);
+ 	if (curr_softif_neigh == softif_neigh)
  		goto out;
  
  	/* we got a neighbor but its mac is 'bigger' than ours  */
@@@ -232,38 -283,39 +283,39 @@@
  		goto out;
  
  	/* switch to new 'smallest neighbor' */
- 	if ((bat_priv->softif_neigh) &&
- 	    (memcmp(softif_neigh->addr, bat_priv->softif_neigh->addr,
+ 	if ((curr_softif_neigh) &&
+ 	    (memcmp(softif_neigh->addr, curr_softif_neigh->addr,
  							ETH_ALEN) < 0)) {
  		bat_dbg(DBG_ROUTES, bat_priv,
  			"Changing mesh exit point from %pM (vid: %d) "
  			"to %pM (vid: %d).\n",
- 			 bat_priv->softif_neigh->addr,
- 			 bat_priv->softif_neigh->vid,
+ 			 curr_softif_neigh->addr,
+ 			 curr_softif_neigh->vid,
  			 softif_neigh->addr, softif_neigh->vid);
- 		softif_neigh_tmp = bat_priv->softif_neigh;
- 		bat_priv->softif_neigh = softif_neigh;
- 		softif_neigh_free_ref(softif_neigh_tmp);
- 		/* we need to hold the additional reference */
- 		goto err;
+ 
+ 		softif_neigh_select(bat_priv, softif_neigh);
+ 		goto out;
  	}
  
  	/* close own batX device and use softif_neigh as exit node */
- 	if ((!bat_priv->softif_neigh) &&
+ 	if ((!curr_softif_neigh) &&
  	    (memcmp(softif_neigh->addr,
  		    bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) {
  		bat_dbg(DBG_ROUTES, bat_priv,
  			"Setting mesh exit point to %pM (vid: %d).\n",
  			softif_neigh->addr, softif_neigh->vid);
- 		bat_priv->softif_neigh = softif_neigh;
- 		/* we need to hold the additional reference */
- 		goto err;
+ 
+ 		softif_neigh_select(bat_priv, softif_neigh);
+ 		goto out;
  	}
  
  out:
  	softif_neigh_free_ref(softif_neigh);
  err:
  	kfree_skb(skb);
+ 	if (curr_softif_neigh)
+ 		softif_neigh_free_ref(curr_softif_neigh);
+ 
  	return;
  }
  
@@@ -321,6 -373,7 +373,7 @@@ int interface_tx(struct sk_buff *skb, s
  	struct bat_priv *bat_priv = netdev_priv(soft_iface);
  	struct bcast_packet *bcast_packet;
  	struct vlan_ethhdr *vhdr;
+ 	struct softif_neigh *curr_softif_neigh = NULL;
  	int data_len = skb->len, ret;
  	short vid = -1;
  	bool do_bcast = false;
@@@ -348,7 -401,8 +401,8 @@@
  	 * if we have a another chosen mesh exit node in range
  	 * it will transport the packets to the mesh
  	 */
- 	if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid))
+ 	curr_softif_neigh = softif_neigh_get_selected(bat_priv);
+ 	if ((curr_softif_neigh) && (curr_softif_neigh->vid == vid))
  		goto dropped;
  
  	/* TODO: check this for locks */
@@@ -410,6 -464,8 +464,8 @@@ dropped
  dropped_freed:
  	bat_priv->stats.tx_dropped++;
  end:
+ 	if (curr_softif_neigh)
+ 		softif_neigh_free_ref(curr_softif_neigh);
  	return NETDEV_TX_OK;
  }
  
@@@ -421,6 -477,7 +477,7 @@@ void interface_rx(struct net_device *so
  	struct unicast_packet *unicast_packet;
  	struct ethhdr *ethhdr;
  	struct vlan_ethhdr *vhdr;
+ 	struct softif_neigh *curr_softif_neigh = NULL;
  	short vid = -1;
  	int ret;
  
@@@ -450,7 -507,8 +507,8 @@@
  	 * if we have a another chosen mesh exit node in range
  	 * it will transport the packets to the non-mesh network
  	 */
- 	if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid)) {
+ 	curr_softif_neigh = softif_neigh_get_selected(bat_priv);
+ 	if (curr_softif_neigh && (curr_softif_neigh->vid == vid)) {
  		skb_push(skb, hdr_size);
  		unicast_packet = (struct unicast_packet *)skb->data;
  
@@@ -461,7 -519,7 +519,7 @@@
  		skb_reset_mac_header(skb);
  
  		memcpy(unicast_packet->dest,
- 		       bat_priv->softif_neigh->addr, ETH_ALEN);
+ 		       curr_softif_neigh->addr, ETH_ALEN);
  		ret = route_unicast_packet(skb, recv_if);
  		if (ret == NET_RX_DROP)
  			goto dropped;
@@@ -474,7 -532,7 +532,7 @@@
  		goto dropped;
  	skb->protocol = eth_type_trans(skb, soft_iface);
  
 -	/* should not be neccesary anymore as we use skb_pull_rcsum()
 +	/* should not be necessary anymore as we use skb_pull_rcsum()
  	 * TODO: please verify this and remove this TODO
  	 * -- Dec 21st 2009, Simon Wunderlich */
  
@@@ -486,11 -544,13 +544,13 @@@
  	soft_iface->last_rx = jiffies;
  
  	netif_rx(skb);
- 	return;
+ 	goto out;
  
  dropped:
  	kfree_skb(skb);
  out:
+ 	if (curr_softif_neigh)
+ 		softif_neigh_free_ref(curr_softif_neigh);
  	return;
  }
  
@@@ -524,6 -584,7 +584,7 @@@ static void interface_setup(struct net_
  	dev->hard_start_xmit = interface_tx;
  #endif
  	dev->destructor = free_netdev;
+ 	dev->tx_queue_len = 0;
  
  	/**
  	 * can't call min_mtu, because the needed variables

-- 
LinuxNextTracking


More information about the linux-merge mailing list