Re: [B.A.T.M.A.N.] [PATCH 5/7] batman-adv: Make bat_priv->curr_gw an rcu protected pointer

Marek Lindner
2011-02-08T13:18:37Z

On Friday 04 February 2011 16:21:34 Linus Lüssing wrote:
> + if (curr_gw) {
> + rcu_read_unlock();
> return;
> + }
>
> - rcu_read_lock();
> if (hlist_empty(&bat_priv->gw_list)) {
> - rcu_read_unlock();
>
> - if (bat_priv->curr_gw) {
> + if (curr_gw) {
> + rcu_read_unlock();
> bat_dbg(DBG_BATMAN, bat_priv,
> "Removing selected gateway - "
> "no gateway in range\n");
> gw_deselect(bat_priv);
> }
> + else
> + rcu_read_unlock();

This is a bit odd here - we return if curr_gw is not NULL and later we print a
message if curr_gw is not NULL ?
The issue existed before your patch came along.

> void gw_check_election(struct bat_priv *bat_priv, struct orig_node
> *orig_node) {
> - struct gw_node *curr_gateway_tmp = bat_priv->curr_gw;
> + struct gw_node *curr_gateway_tmp;
> uint8_t gw_tq_avg, orig_tq_avg;
>
> + rcu_read_lock();
> + curr_gateway_tmp = rcu_dereference(bat_priv->curr_gw);
> if (!curr_gateway_tmp)
> - return;
> + goto rcu_unlock;
>
> if (!curr_gateway_tmp->orig_node)
> goto deselect;

It seems if we jump to "deselect" here the rcu_lock() will never be unlocked.

> @@ -316,7 +342,7 @@ void gw_node_purge(struct bat_priv *bat_priv)
> - if (bat_priv->curr_gw == gw_node)
> + if (rcu_dereference(bat_priv->curr_gw) == gw_node)
> gw_deselect(bat_priv);

At this point we neither hold a rcu_lock() nor the newly created spinlock ...

> spinlock_t gw_list_lock; /* protects gw_list */
> + spinlock_t curr_gw_lock; /* protects curr_gw updates */

Would speak anything against re-using the gw_list_lock ?

Regards,
Marek