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.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 5845dc21ce85..99c2d360888e 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -158,19 +158,25 @@ 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 read_lock(&pathtbl_resize_lock);
162
163 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); 161 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL);
164 if (!new_mpath) { 162 if (!new_mpath) {
165 atomic_dec(&sdata->u.sta.mpaths); 163 atomic_dec(&sdata->u.sta.mpaths);
166 err = -ENOMEM; 164 err = -ENOMEM;
167 goto endadd2; 165 goto endadd2;
168 } 166 }
167 new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL);
168 if (!new_node) {
169 kfree(new_mpath);
170 atomic_dec(&sdata->u.sta.mpaths);
171 err = -ENOMEM;
172 goto endadd2;
173 }
174
175 read_lock(&pathtbl_resize_lock);
169 memcpy(new_mpath->dst, dst, ETH_ALEN); 176 memcpy(new_mpath->dst, dst, ETH_ALEN);
170 new_mpath->dev = dev; 177 new_mpath->dev = dev;
171 new_mpath->flags = 0; 178 new_mpath->flags = 0;
172 skb_queue_head_init(&new_mpath->frame_queue); 179 skb_queue_head_init(&new_mpath->frame_queue);
173 new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL);
174 new_node->mpath = new_mpath; 180 new_node->mpath = new_mpath;
175 new_mpath->timer.data = (unsigned long) new_mpath; 181 new_mpath->timer.data = (unsigned long) new_mpath;
176 new_mpath->timer.function = mesh_path_timer; 182 new_mpath->timer.function = mesh_path_timer;
@@ -202,7 +208,6 @@ int mesh_path_add(u8 *dst, struct net_device *dev)
202 208
203endadd: 209endadd:
204 spin_unlock(&mesh_paths->hashwlock[hash_idx]); 210 spin_unlock(&mesh_paths->hashwlock[hash_idx]);
205endadd2:
206 read_unlock(&pathtbl_resize_lock); 211 read_unlock(&pathtbl_resize_lock);
207 if (!err && grow) { 212 if (!err && grow) {
208 struct mesh_table *oldtbl, *newtbl; 213 struct mesh_table *oldtbl, *newtbl;
@@ -215,10 +220,12 @@ endadd2:
215 return -ENOMEM; 220 return -ENOMEM;
216 } 221 }
217 rcu_assign_pointer(mesh_paths, newtbl); 222 rcu_assign_pointer(mesh_paths, newtbl);
223 write_unlock(&pathtbl_resize_lock);
224
218 synchronize_rcu(); 225 synchronize_rcu();
219 mesh_table_free(oldtbl, false); 226 mesh_table_free(oldtbl, false);
220 write_unlock(&pathtbl_resize_lock);
221 } 227 }
228endadd2:
222 return err; 229 return err;
223} 230}
224 231