hc
2024-05-10 23fa18eaa71266feff7ba8d83022d9e1cc83c65a
kernel/net/ipv4/tcp_metrics.c
....@@ -40,7 +40,7 @@
4040
4141 struct 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 @@
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
5960 static 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
7174 static 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
7882 static 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
8488 struct tcpm_hash_bucket {
....@@ -89,6 +93,7 @@
8993 static unsigned int tcp_metrics_hash_log __read_mostly;
9094
9195 static DEFINE_SPINLOCK(tcp_metrics_lock);
96
+static DEFINE_SEQLOCK(fastopen_seqlock);
9297
9398 static void tcpm_suck_dst(struct tcp_metrics_block *tm,
9499 const struct dst_entry *dst,
....@@ -97,7 +102,7 @@
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 @@
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 @@
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 @@
434454 tp->reordering);
435455 }
436456 }
437
- tm->tcpm_stamp = jiffies;
457
+ WRITE_ONCE(tm->tcpm_stamp, jiffies);
438458 out_unlock:
439459 rcu_read_unlock();
440460 }
....@@ -538,8 +558,6 @@
538558
539559 return ret;
540560 }
541
-
542
-static DEFINE_SEQLOCK(fastopen_seqlock);
543561
544562 void tcp_fastopen_cache_get(struct sock *sk, u16 *mss,
545563 struct tcp_fastopen_cookie *cookie)
....@@ -647,7 +665,7 @@
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 @@
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;