@@ -156,8 +156,13 @@ struct ipgre_net {
156
156
#define tunnels_r tunnels[2]
157
157
#define tunnels_l tunnels[1]
158
158
#define tunnels_wc tunnels[0]
159
+ /*
160
+ * Locking : hash tables are protected by RCU and a spinlock
161
+ */
162
+ static DEFINE_SPINLOCK (ipgre_lock );
159
163
160
- static DEFINE_RWLOCK (ipgre_lock );
164
+ #define for_each_ip_tunnel_rcu (start ) \
165
+ for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
161
166
162
167
/* Given src, dst and key, find appropriate for input tunnel. */
163
168
@@ -175,7 +180,7 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
175
180
ARPHRD_ETHER : ARPHRD_IPGRE ;
176
181
int score , cand_score = 4 ;
177
182
178
- for ( t = ign -> tunnels_r_l [h0 ^ h1 ]; t ; t = t -> next ) {
183
+ for_each_ip_tunnel_rcu ( ign -> tunnels_r_l [h0 ^ h1 ]) {
179
184
if (local != t -> parms .iph .saddr ||
180
185
remote != t -> parms .iph .daddr ||
181
186
key != t -> parms .i_key ||
@@ -200,7 +205,7 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
200
205
}
201
206
}
202
207
203
- for ( t = ign -> tunnels_r [h0 ^ h1 ]; t ; t = t -> next ) {
208
+ for_each_ip_tunnel_rcu ( ign -> tunnels_r [h0 ^ h1 ]) {
204
209
if (remote != t -> parms .iph .daddr ||
205
210
key != t -> parms .i_key ||
206
211
!(t -> dev -> flags & IFF_UP ))
@@ -224,7 +229,7 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
224
229
}
225
230
}
226
231
227
- for ( t = ign -> tunnels_l [h1 ]; t ; t = t -> next ) {
232
+ for_each_ip_tunnel_rcu ( ign -> tunnels_l [h1 ]) {
228
233
if ((local != t -> parms .iph .saddr &&
229
234
(local != t -> parms .iph .daddr ||
230
235
!ipv4_is_multicast (local ))) ||
@@ -250,7 +255,7 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
250
255
}
251
256
}
252
257
253
- for ( t = ign -> tunnels_wc [h1 ]; t ; t = t -> next ) {
258
+ for_each_ip_tunnel_rcu ( ign -> tunnels_wc [h1 ]) {
254
259
if (t -> parms .i_key != key ||
255
260
!(t -> dev -> flags & IFF_UP ))
256
261
continue ;
@@ -276,8 +281,9 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
276
281
if (cand != NULL )
277
282
return cand ;
278
283
279
- if (ign -> fb_tunnel_dev -> flags & IFF_UP )
280
- return netdev_priv (ign -> fb_tunnel_dev );
284
+ dev = ign -> fb_tunnel_dev ;
285
+ if (dev -> flags & IFF_UP )
286
+ return netdev_priv (dev );
281
287
282
288
return NULL ;
283
289
}
@@ -311,10 +317,10 @@ static void ipgre_tunnel_link(struct ipgre_net *ign, struct ip_tunnel *t)
311
317
{
312
318
struct ip_tunnel * * tp = ipgre_bucket (ign , t );
313
319
320
+ spin_lock_bh (& ipgre_lock );
314
321
t -> next = * tp ;
315
- write_lock_bh (& ipgre_lock );
316
- * tp = t ;
317
- write_unlock_bh (& ipgre_lock );
322
+ rcu_assign_pointer (* tp , t );
323
+ spin_unlock_bh (& ipgre_lock );
318
324
}
319
325
320
326
static void ipgre_tunnel_unlink (struct ipgre_net * ign , struct ip_tunnel * t )
@@ -323,9 +329,9 @@ static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t)
323
329
324
330
for (tp = ipgre_bucket (ign , t ); * tp ; tp = & (* tp )-> next ) {
325
331
if (t == * tp ) {
326
- write_lock_bh (& ipgre_lock );
332
+ spin_lock_bh (& ipgre_lock );
327
333
* tp = t -> next ;
328
- write_unlock_bh (& ipgre_lock );
334
+ spin_unlock_bh (& ipgre_lock );
329
335
break ;
330
336
}
331
337
}
@@ -476,7 +482,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
476
482
break ;
477
483
}
478
484
479
- read_lock ( & ipgre_lock );
485
+ rcu_read_lock ( );
480
486
t = ipgre_tunnel_lookup (skb -> dev , iph -> daddr , iph -> saddr ,
481
487
flags & GRE_KEY ?
482
488
* (((__be32 * )p ) + (grehlen / 4 ) - 1 ) : 0 ,
@@ -494,7 +500,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
494
500
t -> err_count = 1 ;
495
501
t -> err_time = jiffies ;
496
502
out :
497
- read_unlock ( & ipgre_lock );
503
+ rcu_read_unlock ( );
498
504
return ;
499
505
}
500
506
@@ -573,7 +579,7 @@ static int ipgre_rcv(struct sk_buff *skb)
573
579
574
580
gre_proto = * (__be16 * )(h + 2 );
575
581
576
- read_lock ( & ipgre_lock );
582
+ rcu_read_lock ( );
577
583
if ((tunnel = ipgre_tunnel_lookup (skb -> dev ,
578
584
iph -> saddr , iph -> daddr , key ,
579
585
gre_proto ))) {
@@ -647,13 +653,13 @@ static int ipgre_rcv(struct sk_buff *skb)
647
653
ipgre_ecn_decapsulate (iph , skb );
648
654
649
655
netif_rx (skb );
650
- read_unlock ( & ipgre_lock );
656
+ rcu_read_unlock ( );
651
657
return (0 );
652
658
}
653
659
icmp_send (skb , ICMP_DEST_UNREACH , ICMP_PORT_UNREACH , 0 );
654
660
655
661
drop :
656
- read_unlock ( & ipgre_lock );
662
+ rcu_read_unlock ( );
657
663
drop_nolock :
658
664
kfree_skb (skb );
659
665
return (0 );
0 commit comments