|
@@ -76,20 +76,18 @@ int my_skb_head_push(struct sk_buff *skb, unsigned int len)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void softif_neigh_free_ref(struct kref *refcount)
|
|
|
+static void softif_neigh_free_rcu(struct rcu_head *rcu)
|
|
|
{
|
|
|
struct softif_neigh *softif_neigh;
|
|
|
|
|
|
- softif_neigh = container_of(refcount, struct softif_neigh, refcount);
|
|
|
+ softif_neigh = container_of(rcu, struct softif_neigh, rcu);
|
|
|
kfree(softif_neigh);
|
|
|
}
|
|
|
|
|
|
-static void softif_neigh_free_rcu(struct rcu_head *rcu)
|
|
|
+static void softif_neigh_free_ref(struct softif_neigh *softif_neigh)
|
|
|
{
|
|
|
- struct softif_neigh *softif_neigh;
|
|
|
-
|
|
|
- softif_neigh = container_of(rcu, struct softif_neigh, rcu);
|
|
|
- kref_put(&softif_neigh->refcount, softif_neigh_free_ref);
|
|
|
+ if (atomic_dec_and_test(&softif_neigh->refcount))
|
|
|
+ call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu);
|
|
|
}
|
|
|
|
|
|
void softif_neigh_purge(struct bat_priv *bat_priv)
|
|
@@ -116,11 +114,10 @@ void softif_neigh_purge(struct bat_priv *bat_priv)
|
|
|
softif_neigh->addr, softif_neigh->vid);
|
|
|
softif_neigh_tmp = bat_priv->softif_neigh;
|
|
|
bat_priv->softif_neigh = NULL;
|
|
|
- kref_put(&softif_neigh_tmp->refcount,
|
|
|
- softif_neigh_free_ref);
|
|
|
+ softif_neigh_free_ref(softif_neigh_tmp);
|
|
|
}
|
|
|
|
|
|
- call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu);
|
|
|
+ softif_neigh_free_ref(softif_neigh);
|
|
|
}
|
|
|
|
|
|
spin_unlock_bh(&bat_priv->softif_neigh_lock);
|
|
@@ -141,8 +138,11 @@ static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
|
|
|
if (softif_neigh->vid != vid)
|
|
|
continue;
|
|
|
|
|
|
+ if (!atomic_inc_not_zero(&softif_neigh->refcount))
|
|
|
+ continue;
|
|
|
+
|
|
|
softif_neigh->last_seen = jiffies;
|
|
|
- goto found;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC);
|
|
@@ -152,15 +152,14 @@ static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
|
|
|
memcpy(softif_neigh->addr, addr, ETH_ALEN);
|
|
|
softif_neigh->vid = vid;
|
|
|
softif_neigh->last_seen = jiffies;
|
|
|
- kref_init(&softif_neigh->refcount);
|
|
|
+ /* initialize with 2 - caller decrements counter by one */
|
|
|
+ atomic_set(&softif_neigh->refcount, 2);
|
|
|
|
|
|
INIT_HLIST_NODE(&softif_neigh->list);
|
|
|
spin_lock_bh(&bat_priv->softif_neigh_lock);
|
|
|
hlist_add_head_rcu(&softif_neigh->list, &bat_priv->softif_neigh_list);
|
|
|
spin_unlock_bh(&bat_priv->softif_neigh_lock);
|
|
|
|
|
|
-found:
|
|
|
- kref_get(&softif_neigh->refcount);
|
|
|
out:
|
|
|
rcu_read_unlock();
|
|
|
return softif_neigh;
|
|
@@ -264,7 +263,7 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
|
|
|
softif_neigh->addr, softif_neigh->vid);
|
|
|
softif_neigh_tmp = bat_priv->softif_neigh;
|
|
|
bat_priv->softif_neigh = softif_neigh;
|
|
|
- kref_put(&softif_neigh_tmp->refcount, softif_neigh_free_ref);
|
|
|
+ softif_neigh_free_ref(softif_neigh_tmp);
|
|
|
/* we need to hold the additional reference */
|
|
|
goto err;
|
|
|
}
|
|
@@ -282,7 +281,7 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
|
|
|
}
|
|
|
|
|
|
out:
|
|
|
- kref_put(&softif_neigh->refcount, softif_neigh_free_ref);
|
|
|
+ softif_neigh_free_ref(softif_neigh);
|
|
|
err:
|
|
|
kfree_skb(skb);
|
|
|
return;
|