@@ -40,7 +40,7 @@ struct tcp_fastopen_metrics {
4040
4141struct tcp_metrics_block {
4242 struct tcp_metrics_block __rcu * tcpm_next ;
43- possible_net_t tcpm_net ;
43+ struct net * tcpm_net ;
4444 struct inetpeer_addr tcpm_saddr ;
4545 struct inetpeer_addr tcpm_daddr ;
4646 unsigned long tcpm_stamp ;
@@ -51,34 +51,38 @@ struct tcp_metrics_block {
5151 struct rcu_head rcu_head ;
5252};
5353
54- static inline struct net * tm_net (struct tcp_metrics_block * tm )
54+ static inline struct net * tm_net (const struct tcp_metrics_block * tm )
5555{
56- return read_pnet (& tm -> tcpm_net );
56+ /* Paired with the WRITE_ONCE() in tcpm_new() */
57+ return READ_ONCE (tm -> tcpm_net );
5758}
5859
5960static bool tcp_metric_locked (struct tcp_metrics_block * tm ,
6061 enum tcp_metric_index idx )
6162{
62- return tm -> tcpm_lock & (1 << idx );
63+ /* Paired with WRITE_ONCE() in tcpm_suck_dst() */
64+ return READ_ONCE (tm -> tcpm_lock ) & (1 << idx );
6365}
6466
65- static u32 tcp_metric_get (struct tcp_metrics_block * tm ,
67+ static u32 tcp_metric_get (const struct tcp_metrics_block * tm ,
6668 enum tcp_metric_index idx )
6769{
68- return tm -> tcpm_vals [idx ];
70+ /* Paired with WRITE_ONCE() in tcp_metric_set() */
71+ return READ_ONCE (tm -> tcpm_vals [idx ]);
6972}
7073
7174static void tcp_metric_set (struct tcp_metrics_block * tm ,
7275 enum tcp_metric_index idx ,
7376 u32 val )
7477{
75- tm -> tcpm_vals [idx ] = val ;
78+ /* Paired with READ_ONCE() in tcp_metric_get() */
79+ WRITE_ONCE (tm -> tcpm_vals [idx ], val );
7680}
7781
7882static bool addr_same (const struct inetpeer_addr * a ,
7983 const struct inetpeer_addr * b )
8084{
81- return inetpeer_addr_cmp ( a , b ) == 0 ;
85+ return ( a -> family == b -> family ) && ! inetpeer_addr_cmp ( a , b ) ;
8286}
8387
8488struct tcpm_hash_bucket {
@@ -89,6 +93,7 @@ static struct tcpm_hash_bucket *tcp_metrics_hash __read_mostly;
8993static unsigned int tcp_metrics_hash_log __read_mostly ;
9094
9195static DEFINE_SPINLOCK (tcp_metrics_lock );
96+ static DEFINE_SEQLOCK (fastopen_seqlock );
9297
9398static void tcpm_suck_dst (struct tcp_metrics_block * tm ,
9499 const struct dst_entry * dst ,
@@ -97,7 +102,7 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm,
97102 u32 msval ;
98103 u32 val ;
99104
100- tm -> tcpm_stamp = jiffies ;
105+ WRITE_ONCE ( tm -> tcpm_stamp , jiffies ) ;
101106
102107 val = 0 ;
103108 if (dst_metric_locked (dst , RTAX_RTT ))
@@ -110,30 +115,42 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm,
110115 val |= 1 << TCP_METRIC_CWND ;
111116 if (dst_metric_locked (dst , RTAX_REORDERING ))
112117 val |= 1 << TCP_METRIC_REORDERING ;
113- tm -> tcpm_lock = val ;
118+ /* Paired with READ_ONCE() in tcp_metric_locked() */
119+ WRITE_ONCE (tm -> tcpm_lock , val );
114120
115121 msval = dst_metric_raw (dst , RTAX_RTT );
116- tm -> tcpm_vals [ TCP_METRIC_RTT ] = msval * USEC_PER_MSEC ;
122+ tcp_metric_set ( tm , TCP_METRIC_RTT , msval * USEC_PER_MSEC ) ;
117123
118124 msval = dst_metric_raw (dst , RTAX_RTTVAR );
119- tm -> tcpm_vals [TCP_METRIC_RTTVAR ] = msval * USEC_PER_MSEC ;
120- tm -> tcpm_vals [TCP_METRIC_SSTHRESH ] = dst_metric_raw (dst , RTAX_SSTHRESH );
121- tm -> tcpm_vals [TCP_METRIC_CWND ] = dst_metric_raw (dst , RTAX_CWND );
122- tm -> tcpm_vals [TCP_METRIC_REORDERING ] = dst_metric_raw (dst , RTAX_REORDERING );
125+ tcp_metric_set (tm , TCP_METRIC_RTTVAR , msval * USEC_PER_MSEC );
126+ tcp_metric_set (tm , TCP_METRIC_SSTHRESH ,
127+ dst_metric_raw (dst , RTAX_SSTHRESH ));
128+ tcp_metric_set (tm , TCP_METRIC_CWND ,
129+ dst_metric_raw (dst , RTAX_CWND ));
130+ tcp_metric_set (tm , TCP_METRIC_REORDERING ,
131+ dst_metric_raw (dst , RTAX_REORDERING ));
123132 if (fastopen_clear ) {
133+ write_seqlock (& fastopen_seqlock );
124134 tm -> tcpm_fastopen .mss = 0 ;
125135 tm -> tcpm_fastopen .syn_loss = 0 ;
126136 tm -> tcpm_fastopen .try_exp = 0 ;
127137 tm -> tcpm_fastopen .cookie .exp = false;
128138 tm -> tcpm_fastopen .cookie .len = 0 ;
139+ write_sequnlock (& fastopen_seqlock );
129140 }
130141}
131142
132143#define TCP_METRICS_TIMEOUT (60 * 60 * HZ)
133144
134- static void tcpm_check_stamp (struct tcp_metrics_block * tm , struct dst_entry * dst )
145+ static void tcpm_check_stamp (struct tcp_metrics_block * tm ,
146+ const struct dst_entry * dst )
135147{
136- if (tm && unlikely (time_after (jiffies , tm -> tcpm_stamp + TCP_METRICS_TIMEOUT )))
148+ unsigned long limit ;
149+
150+ if (!tm )
151+ return ;
152+ limit = READ_ONCE (tm -> tcpm_stamp ) + TCP_METRICS_TIMEOUT ;
153+ if (unlikely (time_after (jiffies , limit )))
137154 tcpm_suck_dst (tm , dst , false);
138155}
139156
@@ -174,20 +191,23 @@ static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst,
174191 oldest = deref_locked (tcp_metrics_hash [hash ].chain );
175192 for (tm = deref_locked (oldest -> tcpm_next ); tm ;
176193 tm = deref_locked (tm -> tcpm_next )) {
177- if (time_before (tm -> tcpm_stamp , oldest -> tcpm_stamp ))
194+ if (time_before (READ_ONCE (tm -> tcpm_stamp ),
195+ READ_ONCE (oldest -> tcpm_stamp )))
178196 oldest = tm ;
179197 }
180198 tm = oldest ;
181199 } else {
182- tm = kmalloc (sizeof (* tm ), GFP_ATOMIC );
200+ tm = kzalloc (sizeof (* tm ), GFP_ATOMIC );
183201 if (!tm )
184202 goto out_unlock ;
185203 }
186- write_pnet (& tm -> tcpm_net , net );
204+ /* Paired with the READ_ONCE() in tm_net() */
205+ WRITE_ONCE (tm -> tcpm_net , net );
206+
187207 tm -> tcpm_saddr = * saddr ;
188208 tm -> tcpm_daddr = * daddr ;
189209
190- tcpm_suck_dst (tm , dst , true );
210+ tcpm_suck_dst (tm , dst , reclaim );
191211
192212 if (likely (!reclaim )) {
193213 tm -> tcpm_next = tcp_metrics_hash [hash ].chain ;
@@ -434,7 +454,7 @@ void tcp_update_metrics(struct sock *sk)
434454 tp -> reordering );
435455 }
436456 }
437- tm -> tcpm_stamp = jiffies ;
457+ WRITE_ONCE ( tm -> tcpm_stamp , jiffies ) ;
438458out_unlock :
439459 rcu_read_unlock ();
440460}
@@ -539,8 +559,6 @@ bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst)
539559 return ret ;
540560}
541561
542- static DEFINE_SEQLOCK (fastopen_seqlock );
543-
544562void tcp_fastopen_cache_get (struct sock * sk , u16 * mss ,
545563 struct tcp_fastopen_cookie * cookie )
546564{
@@ -647,7 +665,7 @@ static int tcp_metrics_fill_info(struct sk_buff *msg,
647665 }
648666
649667 if (nla_put_msecs (msg , TCP_METRICS_ATTR_AGE ,
650- jiffies - tm -> tcpm_stamp ,
668+ jiffies - READ_ONCE ( tm -> tcpm_stamp ) ,
651669 TCP_METRICS_ATTR_PAD ) < 0 )
652670 goto nla_put_failure ;
653671
@@ -658,7 +676,7 @@ static int tcp_metrics_fill_info(struct sk_buff *msg,
658676 if (!nest )
659677 goto nla_put_failure ;
660678 for (i = 0 ; i < TCP_METRIC_MAX_KERNEL + 1 ; i ++ ) {
661- u32 val = tm -> tcpm_vals [ i ] ;
679+ u32 val = tcp_metric_get ( tm , i ) ;
662680
663681 if (!val )
664682 continue ;
0 commit comments