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

Reply via email to