diff options
Diffstat (limited to 'net/mac80211/mesh_pathtbl.c')
-rw-r--r-- | net/mac80211/mesh_pathtbl.c | 30 |
1 files changed, 14 insertions, 16 deletions
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 3cbdbb23d75..a17f2b29904 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -55,10 +55,7 @@ static DEFINE_RWLOCK(pathtbl_resize_lock); */ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) { - __sta_info_get(sta); - if (mpath->next_hop) - sta_info_put(mpath->next_hop); - mpath->next_hop = sta; + rcu_assign_pointer(mpath->next_hop, sta); } @@ -236,7 +233,7 @@ void mesh_plink_broken(struct sta_info *sta) struct mesh_path *mpath; struct mpath_node *node; struct hlist_node *p; - struct net_device *dev = sta->dev; + struct net_device *dev = sta->sdata->dev; int i; rcu_read_lock(); @@ -266,9 +263,9 @@ EXPORT_SYMBOL(mesh_plink_broken); * * RCU notes: this function is called when a mesh plink transitions from ESTAB * to any other state, since ESTAB state is the only one that allows path - * creation. This will happen before the sta can be freed (since we hold - * a reference to it) so any reader in a rcu read block will be protected - * against the plink dissapearing. + * creation. This will happen before the sta can be freed (because + * sta_info_destroy() calls this) so any reader in a rcu read block will be + * protected against the plink disappearing. */ void mesh_path_flush_by_nexthop(struct sta_info *sta) { @@ -280,7 +277,7 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta) for_each_mesh_entry(mesh_paths, p, node, i) { mpath = node->mpath; if (mpath->next_hop == sta) - mesh_path_del(mpath->dst, mpath->dev); + mesh_path_del(mpath->dst, mpath->dev, true); } } @@ -294,7 +291,7 @@ void mesh_path_flush(struct net_device *dev) for_each_mesh_entry(mesh_paths, p, node, i) { mpath = node->mpath; if (mpath->dev == dev) - mesh_path_del(mpath->dst, mpath->dev); + mesh_path_del(mpath->dst, mpath->dev, false); } } @@ -303,8 +300,8 @@ static void mesh_path_node_reclaim(struct rcu_head *rp) struct mpath_node *node = container_of(rp, struct mpath_node, rcu); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(node->mpath->dev); - if (node->mpath->next_hop) - sta_info_put(node->mpath->next_hop); + + rcu_assign_pointer(node->mpath->next_hop, NULL); atomic_dec(&sdata->u.sta.mpaths); kfree(node->mpath); kfree(node); @@ -319,9 +316,10 @@ static void mesh_path_node_reclaim(struct rcu_head *rp) * Returns: 0 if succesful * * State: if the path is being resolved, the deletion will be postponed until - * the path resolution completes or times out. + * the path resolution completes or times out, unless the force parameter + * is given. */ -int mesh_path_del(u8 *addr, struct net_device *dev) +int mesh_path_del(u8 *addr, struct net_device *dev, bool force) { struct mesh_path *mpath; struct mpath_node *node; @@ -340,7 +338,7 @@ int mesh_path_del(u8 *addr, struct net_device *dev) if (mpath->dev == dev && memcmp(addr, mpath->dst, ETH_ALEN) == 0) { spin_lock_bh(&mpath->state_lock); - if (mpath->flags & MESH_PATH_RESOLVING) { + if (!force && mpath->flags & MESH_PATH_RESOLVING) { mpath->flags |= MESH_PATH_DELETE; } else { mpath->flags |= MESH_PATH_RESOLVING; @@ -510,7 +508,7 @@ void mesh_path_expire(struct net_device *dev) time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) { spin_unlock_bh(&mpath->state_lock); - mesh_path_del(mpath->dst, mpath->dev); + mesh_path_del(mpath->dst, mpath->dev, false); } else spin_unlock_bh(&mpath->state_lock); } |