@@ -139,18 +139,22 @@ static int neigh_forced_gc(struct neigh_table *tbl)
139139 nht = rcu_dereference_protected (tbl -> nht ,
140140 lockdep_is_held (& tbl -> lock ));
141141 for (i = 0 ; i <= nht -> hash_mask ; i ++ ) {
142- struct neighbour * n , * * np ;
142+ struct neighbour * n ;
143+ struct neighbour __rcu * * np ;
143144
144145 np = & nht -> hash_buckets [i ];
145- while ((n = * np ) != NULL ) {
146+ while ((n = rcu_dereference_protected (* np ,
147+ lockdep_is_held (& tbl -> lock ))) != NULL ) {
146148 /* Neighbour record may be discarded if:
147149 * - nobody refers to it.
148150 * - it is not permanent
149151 */
150152 write_lock (& n -> lock );
151153 if (atomic_read (& n -> refcnt ) == 1 &&
152154 !(n -> nud_state & NUD_PERMANENT )) {
153- * np = n -> next ;
155+ rcu_assign_pointer (* np ,
156+ rcu_dereference_protected (n -> next ,
157+ lockdep_is_held (& tbl -> lock )));
154158 n -> dead = 1 ;
155159 shrunk = 1 ;
156160 write_unlock (& n -> lock );
@@ -208,14 +212,18 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
208212 lockdep_is_held (& tbl -> lock ));
209213
210214 for (i = 0 ; i <= nht -> hash_mask ; i ++ ) {
211- struct neighbour * n , * * np = & nht -> hash_buckets [i ];
215+ struct neighbour * n ;
216+ struct neighbour __rcu * * np = & nht -> hash_buckets [i ];
212217
213- while ((n = * np ) != NULL ) {
218+ while ((n = rcu_dereference_protected (* np ,
219+ lockdep_is_held (& tbl -> lock ))) != NULL ) {
214220 if (dev && n -> dev != dev ) {
215221 np = & n -> next ;
216222 continue ;
217223 }
218- * np = n -> next ;
224+ rcu_assign_pointer (* np ,
225+ rcu_dereference_protected (n -> next ,
226+ lockdep_is_held (& tbl -> lock )));
219227 write_lock (& n -> lock );
220228 neigh_del_timer (n );
221229 n -> dead = 1 ;
@@ -323,7 +331,7 @@ static struct neigh_hash_table *neigh_hash_alloc(unsigned int entries)
323331 kfree (ret );
324332 return NULL ;
325333 }
326- ret -> hash_buckets = buckets ;
334+ rcu_assign_pointer ( ret -> hash_buckets , buckets ) ;
327335 ret -> hash_mask = entries - 1 ;
328336 get_random_bytes (& ret -> hash_rnd , sizeof (ret -> hash_rnd ));
329337 return ret ;
@@ -362,17 +370,22 @@ static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
362370 for (i = 0 ; i <= old_nht -> hash_mask ; i ++ ) {
363371 struct neighbour * n , * next ;
364372
365- for (n = old_nht -> hash_buckets [i ];
373+ for (n = rcu_dereference_protected (old_nht -> hash_buckets [i ],
374+ lockdep_is_held (& tbl -> lock ));
366375 n != NULL ;
367376 n = next ) {
368377 hash = tbl -> hash (n -> primary_key , n -> dev ,
369378 new_nht -> hash_rnd );
370379
371380 hash &= new_nht -> hash_mask ;
372- next = n -> next ;
373-
374- n -> next = new_nht -> hash_buckets [hash ];
375- new_nht -> hash_buckets [hash ] = n ;
381+ next = rcu_dereference_protected (n -> next ,
382+ lockdep_is_held (& tbl -> lock ));
383+
384+ rcu_assign_pointer (n -> next ,
385+ rcu_dereference_protected (
386+ new_nht -> hash_buckets [hash ],
387+ lockdep_is_held (& tbl -> lock )));
388+ rcu_assign_pointer (new_nht -> hash_buckets [hash ], n );
376389 }
377390 }
378391
@@ -394,15 +407,18 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
394407 rcu_read_lock_bh ();
395408 nht = rcu_dereference_bh (tbl -> nht );
396409 hash_val = tbl -> hash (pkey , dev , nht -> hash_rnd ) & nht -> hash_mask ;
397- read_lock (& tbl -> lock );
398- for (n = nht -> hash_buckets [hash_val ]; n ; n = n -> next ) {
410+
411+ for (n = rcu_dereference_bh (nht -> hash_buckets [hash_val ]);
412+ n != NULL ;
413+ n = rcu_dereference_bh (n -> next )) {
399414 if (dev == n -> dev && !memcmp (n -> primary_key , pkey , key_len )) {
400- neigh_hold (n );
415+ if (!atomic_inc_not_zero (& n -> refcnt ))
416+ n = NULL ;
401417 NEIGH_CACHE_STAT_INC (tbl , hits );
402418 break ;
403419 }
404420 }
405- read_unlock ( & tbl -> lock );
421+
406422 rcu_read_unlock_bh ();
407423 return n ;
408424}
@@ -421,16 +437,19 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
421437 rcu_read_lock_bh ();
422438 nht = rcu_dereference_bh (tbl -> nht );
423439 hash_val = tbl -> hash (pkey , NULL , nht -> hash_rnd ) & nht -> hash_mask ;
424- read_lock (& tbl -> lock );
425- for (n = nht -> hash_buckets [hash_val ]; n ; n = n -> next ) {
440+
441+ for (n = rcu_dereference_bh (nht -> hash_buckets [hash_val ]);
442+ n != NULL ;
443+ n = rcu_dereference_bh (n -> next )) {
426444 if (!memcmp (n -> primary_key , pkey , key_len ) &&
427445 net_eq (dev_net (n -> dev ), net )) {
428- neigh_hold (n );
446+ if (!atomic_inc_not_zero (& n -> refcnt ))
447+ n = NULL ;
429448 NEIGH_CACHE_STAT_INC (tbl , hits );
430449 break ;
431450 }
432451 }
433- read_unlock ( & tbl -> lock );
452+
434453 rcu_read_unlock_bh ();
435454 return n ;
436455}
@@ -483,18 +502,24 @@ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey,
483502 goto out_tbl_unlock ;
484503 }
485504
486- for (n1 = nht -> hash_buckets [hash_val ]; n1 ; n1 = n1 -> next ) {
505+ for (n1 = rcu_dereference_protected (nht -> hash_buckets [hash_val ],
506+ lockdep_is_held (& tbl -> lock ));
507+ n1 != NULL ;
508+ n1 = rcu_dereference_protected (n1 -> next ,
509+ lockdep_is_held (& tbl -> lock ))) {
487510 if (dev == n1 -> dev && !memcmp (n1 -> primary_key , pkey , key_len )) {
488511 neigh_hold (n1 );
489512 rc = n1 ;
490513 goto out_tbl_unlock ;
491514 }
492515 }
493516
494- n -> next = nht -> hash_buckets [hash_val ];
495- nht -> hash_buckets [hash_val ] = n ;
496517 n -> dead = 0 ;
497518 neigh_hold (n );
519+ rcu_assign_pointer (n -> next ,
520+ rcu_dereference_protected (nht -> hash_buckets [hash_val ],
521+ lockdep_is_held (& tbl -> lock )));
522+ rcu_assign_pointer (nht -> hash_buckets [hash_val ], n );
498523 write_unlock_bh (& tbl -> lock );
499524 NEIGH_PRINTK2 ("neigh %p is created.\n" , n );
500525 rc = n ;
@@ -651,6 +676,12 @@ static inline void neigh_parms_put(struct neigh_parms *parms)
651676 neigh_parms_destroy (parms );
652677}
653678
679+ static void neigh_destroy_rcu (struct rcu_head * head )
680+ {
681+ struct neighbour * neigh = container_of (head , struct neighbour , rcu );
682+
683+ kmem_cache_free (neigh -> tbl -> kmem_cachep , neigh );
684+ }
654685/*
655686 * neighbour must already be out of the table;
656687 *
@@ -690,7 +721,7 @@ void neigh_destroy(struct neighbour *neigh)
690721 NEIGH_PRINTK2 ("neigh %p is destroyed.\n" , neigh );
691722
692723 atomic_dec (& neigh -> tbl -> entries );
693- kmem_cache_free ( neigh -> tbl -> kmem_cachep , neigh );
724+ call_rcu ( & neigh -> rcu , neigh_destroy_rcu );
694725}
695726EXPORT_SYMBOL (neigh_destroy );
696727
@@ -731,7 +762,8 @@ static void neigh_connect(struct neighbour *neigh)
731762static void neigh_periodic_work (struct work_struct * work )
732763{
733764 struct neigh_table * tbl = container_of (work , struct neigh_table , gc_work .work );
734- struct neighbour * n , * * np ;
765+ struct neighbour * n ;
766+ struct neighbour __rcu * * np ;
735767 unsigned int i ;
736768 struct neigh_hash_table * nht ;
737769
@@ -756,7 +788,8 @@ static void neigh_periodic_work(struct work_struct *work)
756788 for (i = 0 ; i <= nht -> hash_mask ; i ++ ) {
757789 np = & nht -> hash_buckets [i ];
758790
759- while ((n = * np ) != NULL ) {
791+ while ((n = rcu_dereference_protected (* np ,
792+ lockdep_is_held (& tbl -> lock ))) != NULL ) {
760793 unsigned int state ;
761794
762795 write_lock (& n -> lock );
@@ -1213,8 +1246,8 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
12131246}
12141247
12151248/* This function can be used in contexts, where only old dev_queue_xmit
1216- worked, f.e. if you want to override normal output path (eql, shaper),
1217- but resolution is not made yet.
1249+ * worked, f.e. if you want to override normal output path (eql, shaper),
1250+ * but resolution is not made yet.
12181251 */
12191252
12201253int neigh_compat_output (struct sk_buff * skb )
@@ -2123,7 +2156,7 @@ static void neigh_update_notify(struct neighbour *neigh)
21232156static int neigh_dump_table (struct neigh_table * tbl , struct sk_buff * skb ,
21242157 struct netlink_callback * cb )
21252158{
2126- struct net * net = sock_net (skb -> sk );
2159+ struct net * net = sock_net (skb -> sk );
21272160 struct neighbour * n ;
21282161 int rc , h , s_h = cb -> args [1 ];
21292162 int idx , s_idx = idx = cb -> args [2 ];
@@ -2132,13 +2165,14 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
21322165 rcu_read_lock_bh ();
21332166 nht = rcu_dereference_bh (tbl -> nht );
21342167
2135- read_lock (& tbl -> lock );
21362168 for (h = 0 ; h <= nht -> hash_mask ; h ++ ) {
21372169 if (h < s_h )
21382170 continue ;
21392171 if (h > s_h )
21402172 s_idx = 0 ;
2141- for (n = nht -> hash_buckets [h ], idx = 0 ; n ; n = n -> next ) {
2173+ for (n = rcu_dereference_bh (nht -> hash_buckets [h ]), idx = 0 ;
2174+ n != NULL ;
2175+ n = rcu_dereference_bh (n -> next )) {
21422176 if (!net_eq (dev_net (n -> dev ), net ))
21432177 continue ;
21442178 if (idx < s_idx )
@@ -2150,13 +2184,12 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
21502184 rc = -1 ;
21512185 goto out ;
21522186 }
2153- next :
2187+ next :
21542188 idx ++ ;
21552189 }
21562190 }
21572191 rc = skb -> len ;
21582192out :
2159- read_unlock (& tbl -> lock );
21602193 rcu_read_unlock_bh ();
21612194 cb -> args [1 ] = h ;
21622195 cb -> args [2 ] = idx ;
@@ -2195,11 +2228,13 @@ void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void
21952228 rcu_read_lock_bh ();
21962229 nht = rcu_dereference_bh (tbl -> nht );
21972230
2198- read_lock (& tbl -> lock );
2231+ read_lock (& tbl -> lock ); /* avoid resizes */
21992232 for (chain = 0 ; chain <= nht -> hash_mask ; chain ++ ) {
22002233 struct neighbour * n ;
22012234
2202- for (n = nht -> hash_buckets [chain ]; n ; n = n -> next )
2235+ for (n = rcu_dereference_bh (nht -> hash_buckets [chain ]);
2236+ n != NULL ;
2237+ n = rcu_dereference_bh (n -> next ))
22032238 cb (n , cookie );
22042239 }
22052240 read_unlock (& tbl -> lock );
@@ -2217,16 +2252,20 @@ void __neigh_for_each_release(struct neigh_table *tbl,
22172252 nht = rcu_dereference_protected (tbl -> nht ,
22182253 lockdep_is_held (& tbl -> lock ));
22192254 for (chain = 0 ; chain <= nht -> hash_mask ; chain ++ ) {
2220- struct neighbour * n , * * np ;
2255+ struct neighbour * n ;
2256+ struct neighbour __rcu * * np ;
22212257
22222258 np = & nht -> hash_buckets [chain ];
2223- while ((n = * np ) != NULL ) {
2259+ while ((n = rcu_dereference_protected (* np ,
2260+ lockdep_is_held (& tbl -> lock ))) != NULL ) {
22242261 int release ;
22252262
22262263 write_lock (& n -> lock );
22272264 release = cb (n );
22282265 if (release ) {
2229- * np = n -> next ;
2266+ rcu_assign_pointer (* np ,
2267+ rcu_dereference_protected (n -> next ,
2268+ lockdep_is_held (& tbl -> lock )));
22302269 n -> dead = 1 ;
22312270 } else
22322271 np = & n -> next ;
@@ -2250,7 +2289,7 @@ static struct neighbour *neigh_get_first(struct seq_file *seq)
22502289
22512290 state -> flags &= ~NEIGH_SEQ_IS_PNEIGH ;
22522291 for (bucket = 0 ; bucket <= nht -> hash_mask ; bucket ++ ) {
2253- n = nht -> hash_buckets [bucket ];
2292+ n = rcu_dereference_bh ( nht -> hash_buckets [bucket ]) ;
22542293
22552294 while (n ) {
22562295 if (!net_eq (dev_net (n -> dev ), net ))
@@ -2267,8 +2306,8 @@ static struct neighbour *neigh_get_first(struct seq_file *seq)
22672306 break ;
22682307 if (n -> nud_state & ~NUD_NOARP )
22692308 break ;
2270- next :
2271- n = n -> next ;
2309+ next :
2310+ n = rcu_dereference_bh ( n -> next ) ;
22722311 }
22732312
22742313 if (n )
@@ -2292,7 +2331,7 @@ static struct neighbour *neigh_get_next(struct seq_file *seq,
22922331 if (v )
22932332 return n ;
22942333 }
2295- n = n -> next ;
2334+ n = rcu_dereference_bh ( n -> next ) ;
22962335
22972336 while (1 ) {
22982337 while (n ) {
@@ -2309,8 +2348,8 @@ static struct neighbour *neigh_get_next(struct seq_file *seq,
23092348
23102349 if (n -> nud_state & ~NUD_NOARP )
23112350 break ;
2312- next :
2313- n = n -> next ;
2351+ next :
2352+ n = rcu_dereference_bh ( n -> next ) ;
23142353 }
23152354
23162355 if (n )
@@ -2319,7 +2358,7 @@ static struct neighbour *neigh_get_next(struct seq_file *seq,
23192358 if (++ state -> bucket > nht -> hash_mask )
23202359 break ;
23212360
2322- n = nht -> hash_buckets [state -> bucket ];
2361+ n = rcu_dereference_bh ( nht -> hash_buckets [state -> bucket ]) ;
23232362 }
23242363
23252364 if (n && pos )
@@ -2417,7 +2456,6 @@ static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
24172456}
24182457
24192458void * neigh_seq_start (struct seq_file * seq , loff_t * pos , struct neigh_table * tbl , unsigned int neigh_seq_flags )
2420- __acquires (tbl - > lock )
24212459 __acquires (rcu_bh )
24222460{
24232461 struct neigh_seq_state * state = seq -> private ;
@@ -2428,7 +2466,7 @@ void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl
24282466
24292467 rcu_read_lock_bh ();
24302468 state -> nht = rcu_dereference_bh (tbl -> nht );
2431- read_lock ( & tbl -> lock );
2469+
24322470 return * pos ? neigh_get_idx_any (seq , pos ) : SEQ_START_TOKEN ;
24332471}
24342472EXPORT_SYMBOL (neigh_seq_start );
@@ -2461,13 +2499,8 @@ void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
24612499EXPORT_SYMBOL (neigh_seq_next );
24622500
24632501void neigh_seq_stop (struct seq_file * seq , void * v )
2464- __releases (tbl - > lock )
24652502 __releases (rcu_bh )
24662503{
2467- struct neigh_seq_state * state = seq -> private ;
2468- struct neigh_table * tbl = state -> tbl ;
2469-
2470- read_unlock (& tbl -> lock );
24712504 rcu_read_unlock_bh ();
24722505}
24732506EXPORT_SYMBOL (neigh_seq_stop );
0 commit comments