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