Commit a3e6b12c authored by cozybit Inc's avatar cozybit Inc Committed by John W. Linville

mac80211: Allocate new mesh path and portal tables before taking locks

It is unnecessary to hold the path table resize lock while allocating a
new table.  Allocate first and take lock later.  This resolves a
soft-lockup:

[  293.385799] BUG: soft lockup - CPU#0 stuck for 61s! [kworker/u:3:744]
(...)
[  293.386049] Call Trace:
[  293.386049]  [<c119fd04>] do_raw_read_lock+0x26/0x29
[  293.386049]  [<c14b2982>] _raw_read_lock+0x8/0xa
[  293.386049]  [<c148c178>] mesh_path_add+0xb7/0x24e
[  293.386049]  [<c148b98d>] ? mesh_path_lookup+0x1b/0xa6
[  293.386049]  [<c148ded5>] hwmp_route_info_get+0x276/0x2fd
[  293.386049]  [<c148dfb6>] mesh_rx_path_sel_frame+0x5a/0x5d9
[  293.386049]  [<c102667d>] ? update_curr+0x1cf/0x1d7
[  293.386049]  [<c148b45a>] ieee80211_mesh_rx_queued_mgmt+0x60/0x67
[  293.386049]  [<c147c374>] ieee80211_iface_work+0x1f0/0x258
(...)
Signed-off-by: default avatarJavier Cardona <javier@cozybit.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 09d5b94d
...@@ -65,42 +65,37 @@ void mesh_table_free(struct mesh_table *tbl, bool free_leafs) ...@@ -65,42 +65,37 @@ void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
__mesh_table_free(tbl); __mesh_table_free(tbl);
} }
static struct mesh_table *mesh_table_grow(struct mesh_table *tbl) static int mesh_table_grow(struct mesh_table *oldtbl,
struct mesh_table *newtbl)
{ {
struct mesh_table *newtbl;
struct hlist_head *oldhash; struct hlist_head *oldhash;
struct hlist_node *p, *q; struct hlist_node *p, *q;
int i; int i;
if (atomic_read(&tbl->entries) if (atomic_read(&oldtbl->entries)
< tbl->mean_chain_len * (tbl->hash_mask + 1)) < oldtbl->mean_chain_len * (oldtbl->hash_mask + 1))
goto endgrow; return -EAGAIN;
newtbl = mesh_table_alloc(tbl->size_order + 1);
if (!newtbl)
goto endgrow;
newtbl->free_node = tbl->free_node; newtbl->free_node = oldtbl->free_node;
newtbl->mean_chain_len = tbl->mean_chain_len; newtbl->mean_chain_len = oldtbl->mean_chain_len;
newtbl->copy_node = tbl->copy_node; newtbl->copy_node = oldtbl->copy_node;
atomic_set(&newtbl->entries, atomic_read(&tbl->entries)); atomic_set(&newtbl->entries, atomic_read(&oldtbl->entries));
oldhash = tbl->hash_buckets; oldhash = oldtbl->hash_buckets;
for (i = 0; i <= tbl->hash_mask; i++) for (i = 0; i <= oldtbl->hash_mask; i++)
hlist_for_each(p, &oldhash[i]) hlist_for_each(p, &oldhash[i])
if (tbl->copy_node(p, newtbl) < 0) if (oldtbl->copy_node(p, newtbl) < 0)
goto errcopy; goto errcopy;
return newtbl; return 0;
errcopy: errcopy:
for (i = 0; i <= newtbl->hash_mask; i++) { for (i = 0; i <= newtbl->hash_mask; i++) {
hlist_for_each_safe(p, q, &newtbl->hash_buckets[i]) hlist_for_each_safe(p, q, &newtbl->hash_buckets[i])
tbl->free_node(p, 0); oldtbl->free_node(p, 0);
} }
__mesh_table_free(newtbl); return -ENOMEM;
endgrow:
return NULL;
} }
...@@ -334,10 +329,13 @@ void mesh_mpath_table_grow(void) ...@@ -334,10 +329,13 @@ void mesh_mpath_table_grow(void)
{ {
struct mesh_table *oldtbl, *newtbl; struct mesh_table *oldtbl, *newtbl;
newtbl = mesh_table_alloc(mesh_paths->size_order + 1);
if (!newtbl)
return;
write_lock(&pathtbl_resize_lock); write_lock(&pathtbl_resize_lock);
oldtbl = mesh_paths; oldtbl = mesh_paths;
newtbl = mesh_table_grow(mesh_paths); if (mesh_table_grow(mesh_paths, newtbl) < 0) {
if (!newtbl) { __mesh_table_free(newtbl);
write_unlock(&pathtbl_resize_lock); write_unlock(&pathtbl_resize_lock);
return; return;
} }
...@@ -352,10 +350,13 @@ void mesh_mpp_table_grow(void) ...@@ -352,10 +350,13 @@ void mesh_mpp_table_grow(void)
{ {
struct mesh_table *oldtbl, *newtbl; struct mesh_table *oldtbl, *newtbl;
newtbl = mesh_table_alloc(mpp_paths->size_order + 1);
if (!newtbl)
return;
write_lock(&pathtbl_resize_lock); write_lock(&pathtbl_resize_lock);
oldtbl = mpp_paths; oldtbl = mpp_paths;
newtbl = mesh_table_grow(mpp_paths); if (mesh_table_grow(mpp_paths, newtbl) < 0) {
if (!newtbl) { __mesh_table_free(newtbl);
write_unlock(&pathtbl_resize_lock); write_unlock(&pathtbl_resize_lock);
return; return;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment