@@ -731,7 +731,8 @@ static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
731
731
net_eq (pneigh_net (n ), net ) &&
732
732
(n -> dev == dev || !n -> dev ))
733
733
return n ;
734
- n = n -> next ;
734
+
735
+ n = rcu_dereference_protected (n -> next , 1 );
735
736
}
736
737
return NULL ;
737
738
}
@@ -742,7 +743,7 @@ struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
742
743
unsigned int key_len = tbl -> key_len ;
743
744
u32 hash_val = pneigh_hash (pkey , key_len );
744
745
745
- return __pneigh_lookup_1 (tbl -> phash_buckets [hash_val ],
746
+ return __pneigh_lookup_1 (rcu_dereference_protected ( tbl -> phash_buckets [hash_val ], 1 ) ,
746
747
net , pkey , key_len , dev );
747
748
}
748
749
EXPORT_SYMBOL_GPL (__pneigh_lookup );
@@ -759,7 +760,7 @@ struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl,
759
760
hash_val = pneigh_hash (pkey , key_len );
760
761
761
762
read_lock_bh (& tbl -> lock );
762
- n = __pneigh_lookup_1 (tbl -> phash_buckets [hash_val ],
763
+ n = __pneigh_lookup_1 (rcu_dereference_protected ( tbl -> phash_buckets [hash_val ], 1 ) ,
763
764
net , pkey , key_len , dev );
764
765
read_unlock_bh (& tbl -> lock );
765
766
@@ -778,7 +779,7 @@ struct pneigh_entry *pneigh_create(struct neigh_table *tbl,
778
779
ASSERT_RTNL ();
779
780
780
781
read_lock_bh (& tbl -> lock );
781
- n = __pneigh_lookup_1 (tbl -> phash_buckets [hash_val ],
782
+ n = __pneigh_lookup_1 (rcu_dereference_protected ( tbl -> phash_buckets [hash_val ], 1 ) ,
782
783
net , pkey , key_len , dev );
783
784
read_unlock_bh (& tbl -> lock );
784
785
@@ -803,7 +804,7 @@ struct pneigh_entry *pneigh_create(struct neigh_table *tbl,
803
804
804
805
write_lock_bh (& tbl -> lock );
805
806
n -> next = tbl -> phash_buckets [hash_val ];
806
- tbl -> phash_buckets [hash_val ] = n ;
807
+ rcu_assign_pointer ( tbl -> phash_buckets [hash_val ], n ) ;
807
808
write_unlock_bh (& tbl -> lock );
808
809
out :
809
810
return n ;
@@ -812,16 +813,20 @@ struct pneigh_entry *pneigh_create(struct neigh_table *tbl,
812
813
int pneigh_delete (struct neigh_table * tbl , struct net * net , const void * pkey ,
813
814
struct net_device * dev )
814
815
{
815
- struct pneigh_entry * n , * * np ;
816
- unsigned int key_len = tbl -> key_len ;
817
- u32 hash_val = pneigh_hash (pkey , key_len );
816
+ struct pneigh_entry * n , __rcu * * np ;
817
+ unsigned int key_len ;
818
+ u32 hash_val ;
819
+
820
+ key_len = tbl -> key_len ;
821
+ hash_val = pneigh_hash (pkey , key_len );
818
822
819
823
write_lock_bh (& tbl -> lock );
820
- for (np = & tbl -> phash_buckets [hash_val ]; (n = * np ) != NULL ;
824
+ for (np = & tbl -> phash_buckets [hash_val ];
825
+ (n = rcu_dereference_protected (* np , 1 )) != NULL ;
821
826
np = & n -> next ) {
822
827
if (!memcmp (n -> key , pkey , key_len ) && n -> dev == dev &&
823
828
net_eq (pneigh_net (n ), net )) {
824
- * np = n -> next ;
829
+ rcu_assign_pointer ( * np , n -> next ) ;
825
830
write_unlock_bh (& tbl -> lock );
826
831
if (tbl -> pdestructor )
827
832
tbl -> pdestructor (n );
@@ -838,17 +843,17 @@ static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
838
843
struct net_device * dev ,
839
844
bool skip_perm )
840
845
{
841
- struct pneigh_entry * n , * * np , * freelist = NULL ;
846
+ struct pneigh_entry * n , __rcu * * np , * freelist = NULL ;
842
847
u32 h ;
843
848
844
849
for (h = 0 ; h <= PNEIGH_HASHMASK ; h ++ ) {
845
850
np = & tbl -> phash_buckets [h ];
846
- while ((n = * np ) != NULL ) {
851
+ while ((n = rcu_dereference_protected ( * np , 1 ) ) != NULL ) {
847
852
if (skip_perm && n -> permanent )
848
853
goto skip ;
849
854
if (!dev || n -> dev == dev ) {
850
- * np = n -> next ;
851
- n -> next = freelist ;
855
+ rcu_assign_pointer ( * np , n -> next ) ;
856
+ rcu_assign_pointer ( n -> next , freelist ) ;
852
857
freelist = n ;
853
858
continue ;
854
859
}
@@ -858,7 +863,7 @@ static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
858
863
}
859
864
write_unlock_bh (& tbl -> lock );
860
865
while ((n = freelist )) {
861
- freelist = n -> next ;
866
+ freelist = rcu_dereference_protected ( n -> next , 1 ) ;
862
867
n -> next = NULL ;
863
868
if (tbl -> pdestructor )
864
869
tbl -> pdestructor (n );
@@ -2794,7 +2799,9 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2794
2799
for (h = s_h ; h <= PNEIGH_HASHMASK ; h ++ ) {
2795
2800
if (h > s_h )
2796
2801
s_idx = 0 ;
2797
- for (n = tbl -> phash_buckets [h ], idx = 0 ; n ; n = n -> next ) {
2802
+ for (n = rcu_dereference_protected (tbl -> phash_buckets [h ], 1 ), idx = 0 ;
2803
+ n ;
2804
+ n = rcu_dereference_protected (n -> next , 1 )) {
2798
2805
if (idx < s_idx || pneigh_net (n ) != net )
2799
2806
goto next ;
2800
2807
if (neigh_ifindex_filtered (n -> dev , filter -> dev_idx ) ||
@@ -3288,9 +3295,10 @@ static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
3288
3295
3289
3296
state -> flags |= NEIGH_SEQ_IS_PNEIGH ;
3290
3297
for (bucket = 0 ; bucket <= PNEIGH_HASHMASK ; bucket ++ ) {
3291
- pn = tbl -> phash_buckets [bucket ];
3298
+ pn = rcu_dereference_protected (tbl -> phash_buckets [bucket ], 1 );
3299
+
3292
3300
while (pn && !net_eq (pneigh_net (pn ), net ))
3293
- pn = pn -> next ;
3301
+ pn = rcu_dereference_protected ( pn -> next , 1 ) ;
3294
3302
if (pn )
3295
3303
break ;
3296
3304
}
@@ -3308,15 +3316,17 @@ static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
3308
3316
struct neigh_table * tbl = state -> tbl ;
3309
3317
3310
3318
do {
3311
- pn = pn -> next ;
3319
+ pn = rcu_dereference_protected ( pn -> next , 1 ) ;
3312
3320
} while (pn && !net_eq (pneigh_net (pn ), net ));
3313
3321
3314
3322
while (!pn ) {
3315
3323
if (++ state -> bucket > PNEIGH_HASHMASK )
3316
3324
break ;
3317
- pn = tbl -> phash_buckets [state -> bucket ];
3325
+
3326
+ pn = rcu_dereference_protected (tbl -> phash_buckets [state -> bucket ], 1 );
3327
+
3318
3328
while (pn && !net_eq (pneigh_net (pn ), net ))
3319
- pn = pn -> next ;
3329
+ pn = rcu_dereference_protected ( pn -> next , 1 ) ;
3320
3330
if (pn )
3321
3331
break ;
3322
3332
}
0 commit comments