@@ -134,7 +134,13 @@ static void ipip_fb_tunnel_init(struct net_device *dev);
134
134
static void ipip_tunnel_init (struct net_device * dev );
135
135
static void ipip_tunnel_setup (struct net_device * dev );
136
136
137
- static DEFINE_RWLOCK (ipip_lock );
137
+ /*
138
+ * Locking : hash tables are protected by RCU and a spinlock
139
+ */
140
+ static DEFINE_SPINLOCK (ipip_lock );
141
+
142
+ #define for_each_ip_tunnel_rcu (start ) \
143
+ for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
138
144
139
145
static struct ip_tunnel * ipip_tunnel_lookup (struct net * net ,
140
146
__be32 remote , __be32 local )
@@ -144,20 +150,21 @@ static struct ip_tunnel * ipip_tunnel_lookup(struct net *net,
144
150
struct ip_tunnel * t ;
145
151
struct ipip_net * ipn = net_generic (net , ipip_net_id );
146
152
147
- for ( t = ipn -> tunnels_r_l [h0 ^ h1 ]; t ; t = t -> next ) {
153
+ for_each_ip_tunnel_rcu ( ipn -> tunnels_r_l [h0 ^ h1 ])
148
154
if (local == t -> parms .iph .saddr &&
149
155
remote == t -> parms .iph .daddr && (t -> dev -> flags & IFF_UP ))
150
156
return t ;
151
- }
152
- for ( t = ipn -> tunnels_r [h0 ]; t ; t = t -> next ) {
157
+
158
+ for_each_ip_tunnel_rcu ( ipn -> tunnels_r [h0 ])
153
159
if (remote == t -> parms .iph .daddr && (t -> dev -> flags & IFF_UP ))
154
160
return t ;
155
- }
156
- for ( t = ipn -> tunnels_l [h1 ]; t ; t = t -> next ) {
161
+
162
+ for_each_ip_tunnel_rcu ( ipn -> tunnels_l [h1 ])
157
163
if (local == t -> parms .iph .saddr && (t -> dev -> flags & IFF_UP ))
158
164
return t ;
159
- }
160
- if ((t = ipn -> tunnels_wc [0 ]) != NULL && (t -> dev -> flags & IFF_UP ))
165
+
166
+ t = rcu_dereference (ipn -> tunnels_wc [0 ]);
167
+ if (t && (t -> dev -> flags & IFF_UP ))
161
168
return t ;
162
169
return NULL ;
163
170
}
@@ -193,9 +200,9 @@ static void ipip_tunnel_unlink(struct ipip_net *ipn, struct ip_tunnel *t)
193
200
194
201
for (tp = ipip_bucket (ipn , t ); * tp ; tp = & (* tp )-> next ) {
195
202
if (t == * tp ) {
196
- write_lock_bh (& ipip_lock );
203
+ spin_lock_bh (& ipip_lock );
197
204
* tp = t -> next ;
198
- write_unlock_bh (& ipip_lock );
205
+ spin_unlock_bh (& ipip_lock );
199
206
break ;
200
207
}
201
208
}
@@ -205,10 +212,10 @@ static void ipip_tunnel_link(struct ipip_net *ipn, struct ip_tunnel *t)
205
212
{
206
213
struct ip_tunnel * * tp = ipip_bucket (ipn , t );
207
214
215
+ spin_lock_bh (& ipip_lock );
208
216
t -> next = * tp ;
209
- write_lock_bh (& ipip_lock );
210
- * tp = t ;
211
- write_unlock_bh (& ipip_lock );
217
+ rcu_assign_pointer (* tp , t );
218
+ spin_unlock_bh (& ipip_lock );
212
219
}
213
220
214
221
static struct ip_tunnel * ipip_tunnel_locate (struct net * net ,
@@ -267,9 +274,9 @@ static void ipip_tunnel_uninit(struct net_device *dev)
267
274
struct ipip_net * ipn = net_generic (net , ipip_net_id );
268
275
269
276
if (dev == ipn -> fb_tunnel_dev ) {
270
- write_lock_bh (& ipip_lock );
277
+ spin_lock_bh (& ipip_lock );
271
278
ipn -> tunnels_wc [0 ] = NULL ;
272
- write_unlock_bh (& ipip_lock );
279
+ spin_unlock_bh (& ipip_lock );
273
280
} else
274
281
ipip_tunnel_unlink (ipn , netdev_priv (dev ));
275
282
dev_put (dev );
@@ -318,7 +325,7 @@ static int ipip_err(struct sk_buff *skb, u32 info)
318
325
319
326
err = - ENOENT ;
320
327
321
- read_lock ( & ipip_lock );
328
+ rcu_read_lock ( );
322
329
t = ipip_tunnel_lookup (dev_net (skb -> dev ), iph -> daddr , iph -> saddr );
323
330
if (t == NULL || t -> parms .iph .daddr == 0 )
324
331
goto out ;
@@ -333,7 +340,7 @@ static int ipip_err(struct sk_buff *skb, u32 info)
333
340
t -> err_count = 1 ;
334
341
t -> err_time = jiffies ;
335
342
out :
336
- read_unlock ( & ipip_lock );
343
+ rcu_read_unlock ( );
337
344
return err ;
338
345
}
339
346
@@ -351,11 +358,11 @@ static int ipip_rcv(struct sk_buff *skb)
351
358
struct ip_tunnel * tunnel ;
352
359
const struct iphdr * iph = ip_hdr (skb );
353
360
354
- read_lock ( & ipip_lock );
361
+ rcu_read_lock ( );
355
362
if ((tunnel = ipip_tunnel_lookup (dev_net (skb -> dev ),
356
363
iph -> saddr , iph -> daddr )) != NULL ) {
357
364
if (!xfrm4_policy_check (NULL , XFRM_POLICY_IN , skb )) {
358
- read_unlock ( & ipip_lock );
365
+ rcu_read_unlock ( );
359
366
kfree_skb (skb );
360
367
return 0 ;
361
368
}
@@ -374,10 +381,10 @@ static int ipip_rcv(struct sk_buff *skb)
374
381
nf_reset (skb );
375
382
ipip_ecn_decapsulate (iph , skb );
376
383
netif_rx (skb );
377
- read_unlock ( & ipip_lock );
384
+ rcu_read_unlock ( );
378
385
return 0 ;
379
386
}
380
- read_unlock ( & ipip_lock );
387
+ rcu_read_unlock ( );
381
388
382
389
return -1 ;
383
390
}
0 commit comments