@@ -68,36 +68,45 @@ static unsigned int ip_tunnel_hash(struct ip_tunnel_net *itn,
6868 IP_TNL_HASH_BITS );
6969}
7070
71- static inline void __tunnel_dst_set (struct ip_tunnel * t , struct dst_entry * dst )
71+ static inline void __tunnel_dst_set (struct ip_tunnel_dst * idst ,
72+ struct dst_entry * dst )
7273{
7374 struct dst_entry * old_dst ;
7475
7576 if (dst && (dst -> flags & DST_NOCACHE ))
7677 dst = NULL ;
7778
78- spin_lock_bh (& t -> dst_lock );
79- old_dst = rcu_dereference_raw ( t -> dst_cache );
80- rcu_assign_pointer (t -> dst_cache , dst );
79+ spin_lock_bh (& idst -> lock );
80+ old_dst = rcu_dereference ( idst -> dst );
81+ rcu_assign_pointer (idst -> dst , dst );
8182 dst_release (old_dst );
82- spin_unlock_bh (& t -> dst_lock );
83+ spin_unlock_bh (& idst -> lock );
8384}
8485
8586static inline void tunnel_dst_set (struct ip_tunnel * t , struct dst_entry * dst )
8687{
87- __tunnel_dst_set (t , dst );
88+ __tunnel_dst_set (this_cpu_ptr ( t -> dst_cache ) , dst );
8889}
8990
9091static inline void tunnel_dst_reset (struct ip_tunnel * t )
9192{
9293 tunnel_dst_set (t , NULL );
9394}
9495
96+ static void tunnel_dst_reset_all (struct ip_tunnel * t )
97+ {
98+ int i ;
99+
100+ for_each_possible_cpu (i )
101+ __tunnel_dst_set (per_cpu_ptr (t -> dst_cache , i ), NULL );
102+ }
103+
95104static inline struct dst_entry * tunnel_dst_get (struct ip_tunnel * t )
96105{
97106 struct dst_entry * dst ;
98107
99108 rcu_read_lock ();
100- dst = rcu_dereference (t -> dst_cache );
109+ dst = rcu_dereference (this_cpu_ptr ( t -> dst_cache ) -> dst );
101110 if (dst )
102111 dst_hold (dst );
103112 rcu_read_unlock ();
@@ -755,7 +764,7 @@ static void ip_tunnel_update(struct ip_tunnel_net *itn,
755764 if (set_mtu )
756765 dev -> mtu = mtu ;
757766 }
758- tunnel_dst_reset (t );
767+ tunnel_dst_reset_all (t );
759768 netdev_state_change (dev );
760769}
761770
@@ -871,6 +880,7 @@ static void ip_tunnel_dev_free(struct net_device *dev)
871880 struct ip_tunnel * tunnel = netdev_priv (dev );
872881
873882 gro_cells_destroy (& tunnel -> gro_cells );
883+ free_percpu (tunnel -> dst_cache );
874884 free_percpu (dev -> tstats );
875885 free_netdev (dev );
876886}
@@ -1049,8 +1059,21 @@ int ip_tunnel_init(struct net_device *dev)
10491059 u64_stats_init (& ipt_stats -> syncp );
10501060 }
10511061
1062+ tunnel -> dst_cache = alloc_percpu (struct ip_tunnel_dst );
1063+ if (!tunnel -> dst_cache ) {
1064+ free_percpu (dev -> tstats );
1065+ return - ENOMEM ;
1066+ }
1067+
1068+ for_each_possible_cpu (i ) {
1069+ struct ip_tunnel_dst * idst = per_cpu_ptr (tunnel -> dst_cache , i );
1070+ idst -> dst = NULL ;
1071+ spin_lock_init (& idst -> lock );
1072+ }
1073+
10521074 err = gro_cells_init (& tunnel -> gro_cells , dev );
10531075 if (err ) {
1076+ free_percpu (tunnel -> dst_cache );
10541077 free_percpu (dev -> tstats );
10551078 return err ;
10561079 }
@@ -1061,9 +1084,6 @@ int ip_tunnel_init(struct net_device *dev)
10611084 iph -> version = 4 ;
10621085 iph -> ihl = 5 ;
10631086
1064- tunnel -> dst_cache = NULL ;
1065- spin_lock_init (& tunnel -> dst_lock );
1066-
10671087 return 0 ;
10681088}
10691089EXPORT_SYMBOL_GPL (ip_tunnel_init );
@@ -1079,7 +1099,7 @@ void ip_tunnel_uninit(struct net_device *dev)
10791099 if (itn -> fb_tunnel_dev != dev )
10801100 ip_tunnel_del (netdev_priv (dev ));
10811101
1082- tunnel_dst_reset (tunnel );
1102+ tunnel_dst_reset_all (tunnel );
10831103}
10841104EXPORT_SYMBOL_GPL (ip_tunnel_uninit );
10851105
0 commit comments