@@ -119,10 +119,18 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
119
119
{
120
120
struct hlist_head * mesh_hash ;
121
121
struct hlist_node * p , * q ;
122
- struct mpath_node * gate ;
122
+ struct mesh_path * gate ;
123
123
int i ;
124
124
125
125
mesh_hash = tbl -> hash_buckets ;
126
+ if (free_leafs ) {
127
+ spin_lock_bh (& tbl -> gates_lock );
128
+ hlist_for_each_entry_safe (gate , q ,
129
+ tbl -> known_gates , gate_list )
130
+ hlist_del (& gate -> gate_list );
131
+ kfree (tbl -> known_gates );
132
+ spin_unlock_bh (& tbl -> gates_lock );
133
+ }
126
134
for (i = 0 ; i <= tbl -> hash_mask ; i ++ ) {
127
135
spin_lock_bh (& tbl -> hashwlock [i ]);
128
136
hlist_for_each_safe (p , q , & mesh_hash [i ]) {
@@ -131,16 +139,6 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
131
139
}
132
140
spin_unlock_bh (& tbl -> hashwlock [i ]);
133
141
}
134
- if (free_leafs ) {
135
- spin_lock_bh (& tbl -> gates_lock );
136
- hlist_for_each_entry_safe (gate , q ,
137
- tbl -> known_gates , list ) {
138
- hlist_del (& gate -> list );
139
- kfree (gate );
140
- }
141
- kfree (tbl -> known_gates );
142
- spin_unlock_bh (& tbl -> gates_lock );
143
- }
144
142
145
143
__mesh_table_free (tbl );
146
144
}
@@ -431,30 +429,26 @@ mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx)
431
429
int mesh_path_add_gate (struct mesh_path * mpath )
432
430
{
433
431
struct mesh_table * tbl ;
434
- struct mpath_node * gate , * new_gate ;
435
432
int err ;
436
433
437
434
rcu_read_lock ();
438
435
tbl = rcu_dereference (mpath -> sdata -> u .mesh .mesh_paths );
439
436
440
- hlist_for_each_entry_rcu (gate , tbl -> known_gates , list )
441
- if (gate -> mpath == mpath ) {
442
- err = - EEXIST ;
443
- goto err_rcu ;
444
- }
445
-
446
- new_gate = kzalloc (sizeof (struct mpath_node ), GFP_ATOMIC );
447
- if (!new_gate ) {
448
- err = - ENOMEM ;
437
+ spin_lock_bh (& mpath -> state_lock );
438
+ if (mpath -> is_gate ) {
439
+ err = - EEXIST ;
440
+ spin_unlock_bh (& mpath -> state_lock );
449
441
goto err_rcu ;
450
442
}
451
-
452
443
mpath -> is_gate = true;
453
444
mpath -> sdata -> u .mesh .num_gates ++ ;
454
- new_gate -> mpath = mpath ;
455
- spin_lock_bh (& tbl -> gates_lock );
456
- hlist_add_head_rcu (& new_gate -> list , tbl -> known_gates );
457
- spin_unlock_bh (& tbl -> gates_lock );
445
+
446
+ spin_lock (& tbl -> gates_lock );
447
+ hlist_add_head_rcu (& mpath -> gate_list , tbl -> known_gates );
448
+ spin_unlock (& tbl -> gates_lock );
449
+
450
+ spin_unlock_bh (& mpath -> state_lock );
451
+
458
452
mpath_dbg (mpath -> sdata ,
459
453
"Mesh path: Recorded new gate: %pM. %d known gates\n" ,
460
454
mpath -> dst , mpath -> sdata -> u .mesh .num_gates );
@@ -468,28 +462,22 @@ int mesh_path_add_gate(struct mesh_path *mpath)
468
462
* mesh_gate_del - remove a mesh gate from the list of known gates
469
463
* @tbl: table which holds our list of known gates
470
464
* @mpath: gate mpath
471
- *
472
- * Locking: must be called inside rcu_read_lock() section
473
465
*/
474
466
static void mesh_gate_del (struct mesh_table * tbl , struct mesh_path * mpath )
475
467
{
476
- struct mpath_node * gate ;
477
- struct hlist_node * q ;
468
+ lockdep_assert_held (& mpath -> state_lock );
469
+ if (!mpath -> is_gate )
470
+ return ;
478
471
479
- hlist_for_each_entry_safe (gate , q , tbl -> known_gates , list ) {
480
- if (gate -> mpath != mpath )
481
- continue ;
482
- spin_lock_bh (& tbl -> gates_lock );
483
- hlist_del_rcu (& gate -> list );
484
- kfree_rcu (gate , rcu );
485
- spin_unlock_bh (& tbl -> gates_lock );
486
- mpath -> sdata -> u .mesh .num_gates -- ;
487
- mpath -> is_gate = false;
488
- mpath_dbg (mpath -> sdata ,
489
- "Mesh path: Deleted gate: %pM. %d known gates\n" ,
490
- mpath -> dst , mpath -> sdata -> u .mesh .num_gates );
491
- break ;
492
- }
472
+ mpath -> is_gate = false;
473
+ spin_lock_bh (& tbl -> gates_lock );
474
+ hlist_del_rcu (& mpath -> gate_list );
475
+ mpath -> sdata -> u .mesh .num_gates -- ;
476
+ spin_unlock_bh (& tbl -> gates_lock );
477
+
478
+ mpath_dbg (mpath -> sdata ,
479
+ "Mesh path: Deleted gate: %pM. %d known gates\n" ,
480
+ mpath -> dst , mpath -> sdata -> u .mesh .num_gates );
493
481
}
494
482
495
483
/**
@@ -781,13 +769,13 @@ static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node)
781
769
struct mesh_path * mpath = node -> mpath ;
782
770
struct ieee80211_sub_if_data * sdata = node -> mpath -> sdata ;
783
771
784
- spin_lock (& mpath -> state_lock );
772
+ spin_lock_bh (& mpath -> state_lock );
785
773
mpath -> flags |= MESH_PATH_RESOLVING ;
786
774
if (mpath -> is_gate )
787
775
mesh_gate_del (tbl , mpath );
788
776
hlist_del_rcu (& node -> list );
789
777
call_rcu (& node -> rcu , mesh_path_node_reclaim );
790
- spin_unlock (& mpath -> state_lock );
778
+ spin_unlock_bh (& mpath -> state_lock );
791
779
atomic_dec (& sdata -> u .mesh .mpaths );
792
780
atomic_dec (& tbl -> entries );
793
781
}
@@ -999,7 +987,7 @@ int mesh_path_send_to_gates(struct mesh_path *mpath)
999
987
struct ieee80211_sub_if_data * sdata = mpath -> sdata ;
1000
988
struct mesh_table * tbl ;
1001
989
struct mesh_path * from_mpath = mpath ;
1002
- struct mpath_node * gate = NULL ;
990
+ struct mesh_path * gate = NULL ;
1003
991
bool copy = false;
1004
992
struct hlist_head * known_gates ;
1005
993
@@ -1011,22 +999,22 @@ int mesh_path_send_to_gates(struct mesh_path *mpath)
1011
999
if (!known_gates )
1012
1000
return - EHOSTUNREACH ;
1013
1001
1014
- hlist_for_each_entry_rcu (gate , known_gates , list ) {
1015
- if (gate -> mpath -> flags & MESH_PATH_ACTIVE ) {
1016
- mpath_dbg (sdata , "Forwarding to %pM\n" , gate -> mpath -> dst );
1017
- mesh_path_move_to_queue (gate -> mpath , from_mpath , copy );
1018
- from_mpath = gate -> mpath ;
1002
+ hlist_for_each_entry_rcu (gate , known_gates , gate_list ) {
1003
+ if (gate -> flags & MESH_PATH_ACTIVE ) {
1004
+ mpath_dbg (sdata , "Forwarding to %pM\n" , gate -> dst );
1005
+ mesh_path_move_to_queue (gate , from_mpath , copy );
1006
+ from_mpath = gate ;
1019
1007
copy = true;
1020
1008
} else {
1021
1009
mpath_dbg (sdata ,
1022
1010
"Not forwarding to %pM (flags %#x)\n" ,
1023
- gate -> mpath -> dst , gate -> mpath -> flags );
1011
+ gate -> dst , gate -> flags );
1024
1012
}
1025
1013
}
1026
1014
1027
- hlist_for_each_entry_rcu (gate , known_gates , list ) {
1028
- mpath_dbg (sdata , "Sending to %pM\n" , gate -> mpath -> dst );
1029
- mesh_path_tx_pending (gate -> mpath );
1015
+ hlist_for_each_entry_rcu (gate , known_gates , gate_list ) {
1016
+ mpath_dbg (sdata , "Sending to %pM\n" , gate -> dst );
1017
+ mesh_path_tx_pending (gate );
1030
1018
}
1031
1019
1032
1020
return (from_mpath == mpath ) ? - EHOSTUNREACH : 0 ;
0 commit comments