@@ -77,8 +77,17 @@ struct sit_net {
7777 struct net_device * fb_tunnel_dev ;
7878};
7979
80- static DEFINE_RWLOCK (ipip6_lock );
80+ /*
81+ * Locking : hash tables are protected by RCU and a spinlock
82+ */
83+ static DEFINE_SPINLOCK (ipip6_lock );
84+
85+ #define for_each_ip_tunnel_rcu (start ) \
86+ for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
8187
88+ /*
89+ * Must be invoked with rcu_read_lock
90+ */
8291static struct ip_tunnel * ipip6_tunnel_lookup (struct net * net ,
8392 struct net_device * dev , __be32 remote , __be32 local )
8493{
@@ -87,26 +96,26 @@ static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net,
8796 struct ip_tunnel * t ;
8897 struct sit_net * sitn = net_generic (net , sit_net_id );
8998
90- for ( t = sitn -> tunnels_r_l [h0 ^ h1 ]; t ; t = t -> next ) {
99+ for_each_ip_tunnel_rcu ( sitn -> tunnels_r_l [h0 ^ h1 ]) {
91100 if (local == t -> parms .iph .saddr &&
92101 remote == t -> parms .iph .daddr &&
93102 (!dev || !t -> parms .link || dev -> iflink == t -> parms .link ) &&
94103 (t -> dev -> flags & IFF_UP ))
95104 return t ;
96105 }
97- for ( t = sitn -> tunnels_r [h0 ]; t ; t = t -> next ) {
106+ for_each_ip_tunnel_rcu ( sitn -> tunnels_r [h0 ]) {
98107 if (remote == t -> parms .iph .daddr &&
99108 (!dev || !t -> parms .link || dev -> iflink == t -> parms .link ) &&
100109 (t -> dev -> flags & IFF_UP ))
101110 return t ;
102111 }
103- for ( t = sitn -> tunnels_l [h1 ]; t ; t = t -> next ) {
112+ for_each_ip_tunnel_rcu ( sitn -> tunnels_l [h1 ]) {
104113 if (local == t -> parms .iph .saddr &&
105114 (!dev || !t -> parms .link || dev -> iflink == t -> parms .link ) &&
106115 (t -> dev -> flags & IFF_UP ))
107116 return t ;
108117 }
109- t = sitn -> tunnels_wc [0 ];
118+ t = rcu_dereference ( sitn -> tunnels_wc [0 ]) ;
110119 if ((t != NULL ) && (t -> dev -> flags & IFF_UP ))
111120 return t ;
112121 return NULL ;
@@ -143,9 +152,9 @@ static void ipip6_tunnel_unlink(struct sit_net *sitn, struct ip_tunnel *t)
143152
144153 for (tp = ipip6_bucket (sitn , t ); * tp ; tp = & (* tp )-> next ) {
145154 if (t == * tp ) {
146- write_lock_bh (& ipip6_lock );
155+ spin_lock_bh (& ipip6_lock );
147156 * tp = t -> next ;
148- write_unlock_bh (& ipip6_lock );
157+ spin_unlock_bh (& ipip6_lock );
149158 break ;
150159 }
151160 }
@@ -155,10 +164,10 @@ static void ipip6_tunnel_link(struct sit_net *sitn, struct ip_tunnel *t)
155164{
156165 struct ip_tunnel * * tp = ipip6_bucket (sitn , t );
157166
167+ spin_lock_bh (& ipip6_lock );
158168 t -> next = * tp ;
159- write_lock_bh (& ipip6_lock );
160- * tp = t ;
161- write_unlock_bh (& ipip6_lock );
169+ rcu_assign_pointer (* tp , t );
170+ spin_unlock_bh (& ipip6_lock );
162171}
163172
164173static void ipip6_tunnel_clone_6rd (struct net_device * dev , struct sit_net * sitn )
@@ -447,9 +456,9 @@ static void ipip6_tunnel_uninit(struct net_device *dev)
447456 struct sit_net * sitn = net_generic (net , sit_net_id );
448457
449458 if (dev == sitn -> fb_tunnel_dev ) {
450- write_lock_bh (& ipip6_lock );
459+ spin_lock_bh (& ipip6_lock );
451460 sitn -> tunnels_wc [0 ] = NULL ;
452- write_unlock_bh (& ipip6_lock );
461+ spin_unlock_bh (& ipip6_lock );
453462 dev_put (dev );
454463 } else {
455464 ipip6_tunnel_unlink (sitn , netdev_priv (dev ));
@@ -502,7 +511,7 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
502511
503512 err = - ENOENT ;
504513
505- read_lock ( & ipip6_lock );
514+ rcu_read_lock ( );
506515 t = ipip6_tunnel_lookup (dev_net (skb -> dev ),
507516 skb -> dev ,
508517 iph -> daddr ,
@@ -520,7 +529,7 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
520529 t -> err_count = 1 ;
521530 t -> err_time = jiffies ;
522531out :
523- read_unlock ( & ipip6_lock );
532+ rcu_read_unlock ( );
524533 return err ;
525534}
526535
@@ -540,7 +549,7 @@ static int ipip6_rcv(struct sk_buff *skb)
540549
541550 iph = ip_hdr (skb );
542551
543- read_lock ( & ipip6_lock );
552+ rcu_read_lock ( );
544553 tunnel = ipip6_tunnel_lookup (dev_net (skb -> dev ), skb -> dev ,
545554 iph -> saddr , iph -> daddr );
546555 if (tunnel != NULL ) {
@@ -554,7 +563,7 @@ static int ipip6_rcv(struct sk_buff *skb)
554563 if ((tunnel -> dev -> priv_flags & IFF_ISATAP ) &&
555564 !isatap_chksrc (skb , iph , tunnel )) {
556565 tunnel -> dev -> stats .rx_errors ++ ;
557- read_unlock ( & ipip6_lock );
566+ rcu_read_unlock ( );
558567 kfree_skb (skb );
559568 return 0 ;
560569 }
@@ -565,12 +574,12 @@ static int ipip6_rcv(struct sk_buff *skb)
565574 nf_reset (skb );
566575 ipip6_ecn_decapsulate (iph , skb );
567576 netif_rx (skb );
568- read_unlock ( & ipip6_lock );
577+ rcu_read_unlock ( );
569578 return 0 ;
570579 }
571580
572581 icmp_send (skb , ICMP_DEST_UNREACH , ICMP_PORT_UNREACH , 0 );
573- read_unlock ( & ipip6_lock );
582+ rcu_read_unlock ( );
574583out :
575584 kfree_skb (skb );
576585 return 0 ;
0 commit comments