aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mesh_pathtbl.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mesh_pathtbl.c')
-rw-r--r--net/mac80211/mesh_pathtbl.c54
1 files changed, 27 insertions, 27 deletions
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 99c2d360888e..5f88a2e6ee50 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -158,19 +158,14 @@ int mesh_path_add(u8 *dst, struct net_device *dev)
158 if (atomic_add_unless(&sdata->u.sta.mpaths, 1, MESH_MAX_MPATHS) == 0) 158 if (atomic_add_unless(&sdata->u.sta.mpaths, 1, MESH_MAX_MPATHS) == 0)
159 return -ENOSPC; 159 return -ENOSPC;
160 160
161 err = -ENOMEM;
161 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); 162 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL);
162 if (!new_mpath) { 163 if (!new_mpath)
163 atomic_dec(&sdata->u.sta.mpaths); 164 goto err_path_alloc;
164 err = -ENOMEM; 165
165 goto endadd2;
166 }
167 new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); 166 new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL);
168 if (!new_node) { 167 if (!new_node)
169 kfree(new_mpath); 168 goto err_node_alloc;
170 atomic_dec(&sdata->u.sta.mpaths);
171 err = -ENOMEM;
172 goto endadd2;
173 }
174 169
175 read_lock(&pathtbl_resize_lock); 170 read_lock(&pathtbl_resize_lock);
176 memcpy(new_mpath->dst, dst, ETH_ALEN); 171 memcpy(new_mpath->dst, dst, ETH_ALEN);
@@ -189,16 +184,11 @@ int mesh_path_add(u8 *dst, struct net_device *dev)
189 184
190 spin_lock(&mesh_paths->hashwlock[hash_idx]); 185 spin_lock(&mesh_paths->hashwlock[hash_idx]);
191 186
187 err = -EEXIST;
192 hlist_for_each_entry(node, n, bucket, list) { 188 hlist_for_each_entry(node, n, bucket, list) {
193 mpath = node->mpath; 189 mpath = node->mpath;
194 if (mpath->dev == dev && memcmp(dst, mpath->dst, ETH_ALEN) 190 if (mpath->dev == dev && memcmp(dst, mpath->dst, ETH_ALEN) == 0)
195 == 0) { 191 goto err_exists;
196 err = -EEXIST;
197 atomic_dec(&sdata->u.sta.mpaths);
198 kfree(new_node);
199 kfree(new_mpath);
200 goto endadd;
201 }
202 } 192 }
203 193
204 hlist_add_head_rcu(&new_node->list, bucket); 194 hlist_add_head_rcu(&new_node->list, bucket);
@@ -206,10 +196,9 @@ int mesh_path_add(u8 *dst, struct net_device *dev)
206 mesh_paths->mean_chain_len * (mesh_paths->hash_mask + 1)) 196 mesh_paths->mean_chain_len * (mesh_paths->hash_mask + 1))
207 grow = 1; 197 grow = 1;
208 198
209endadd:
210 spin_unlock(&mesh_paths->hashwlock[hash_idx]); 199 spin_unlock(&mesh_paths->hashwlock[hash_idx]);
211 read_unlock(&pathtbl_resize_lock); 200 read_unlock(&pathtbl_resize_lock);
212 if (!err && grow) { 201 if (grow) {
213 struct mesh_table *oldtbl, *newtbl; 202 struct mesh_table *oldtbl, *newtbl;
214 203
215 write_lock(&pathtbl_resize_lock); 204 write_lock(&pathtbl_resize_lock);
@@ -217,7 +206,7 @@ endadd:
217 newtbl = mesh_table_grow(mesh_paths); 206 newtbl = mesh_table_grow(mesh_paths);
218 if (!newtbl) { 207 if (!newtbl) {
219 write_unlock(&pathtbl_resize_lock); 208 write_unlock(&pathtbl_resize_lock);
220 return -ENOMEM; 209 return 0;
221 } 210 }
222 rcu_assign_pointer(mesh_paths, newtbl); 211 rcu_assign_pointer(mesh_paths, newtbl);
223 write_unlock(&pathtbl_resize_lock); 212 write_unlock(&pathtbl_resize_lock);
@@ -225,7 +214,16 @@ endadd:
225 synchronize_rcu(); 214 synchronize_rcu();
226 mesh_table_free(oldtbl, false); 215 mesh_table_free(oldtbl, false);
227 } 216 }
228endadd2: 217 return 0;
218
219err_exists:
220 spin_unlock(&mesh_paths->hashwlock[hash_idx]);
221 read_unlock(&pathtbl_resize_lock);
222 kfree(new_node);
223err_node_alloc:
224 kfree(new_mpath);
225err_path_alloc:
226 atomic_dec(&sdata->u.sta.mpaths);
229 return err; 227 return err;
230} 228}
231 229
@@ -264,7 +262,6 @@ void mesh_plink_broken(struct sta_info *sta)
264 } 262 }
265 rcu_read_unlock(); 263 rcu_read_unlock();
266} 264}
267EXPORT_SYMBOL(mesh_plink_broken);
268 265
269/** 266/**
270 * mesh_path_flush_by_nexthop - Deletes mesh paths if their next hop matches 267 * mesh_path_flush_by_nexthop - Deletes mesh paths if their next hop matches
@@ -460,25 +457,28 @@ static void mesh_path_node_free(struct hlist_node *p, bool free_leafs)
460 struct mpath_node *node = hlist_entry(p, struct mpath_node, list); 457 struct mpath_node *node = hlist_entry(p, struct mpath_node, list);
461 mpath = node->mpath; 458 mpath = node->mpath;
462 hlist_del_rcu(p); 459 hlist_del_rcu(p);
463 synchronize_rcu();
464 if (free_leafs) 460 if (free_leafs)
465 kfree(mpath); 461 kfree(mpath);
466 kfree(node); 462 kfree(node);
467} 463}
468 464
469static void mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) 465static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl)
470{ 466{
471 struct mesh_path *mpath; 467 struct mesh_path *mpath;
472 struct mpath_node *node, *new_node; 468 struct mpath_node *node, *new_node;
473 u32 hash_idx; 469 u32 hash_idx;
474 470
471 new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
472 if (new_node == NULL)
473 return -ENOMEM;
474
475 node = hlist_entry(p, struct mpath_node, list); 475 node = hlist_entry(p, struct mpath_node, list);
476 mpath = node->mpath; 476 mpath = node->mpath;
477 new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL);
478 new_node->mpath = mpath; 477 new_node->mpath = mpath;
479 hash_idx = mesh_table_hash(mpath->dst, mpath->dev, newtbl); 478 hash_idx = mesh_table_hash(mpath->dst, mpath->dev, newtbl);
480 hlist_add_head(&new_node->list, 479 hlist_add_head(&new_node->list,
481 &newtbl->hash_buckets[hash_idx]); 480 &newtbl->hash_buckets[hash_idx]);
481 return 0;
482} 482}
483 483
484int mesh_pathtbl_init(void) 484int mesh_pathtbl_init(void)