Skip to content

Commit 0a970c6

Browse files
committed
tcp: add tcp_sock_set_cork
jira LE-3571 Rebuild_History Non-Buildable kernel-4.18.0-553.60.1.el8_10 commit-author Christoph Hellwig <hch@lst.de> commit db10538 Empty-Commit: Cherry-Pick Conflicts during history rebuild. Will be included in final tarball splat. Ref for failed cherry-pick at: ciq/ciq_backports/kernel-4.18.0-553.60.1.el8_10/db10538a.failed Add a helper to directly set the TCP_CORK sockopt from kernel space without going through a fake uaccess. Cleanup the callers to avoid pointless wrappers now that this is a simple function call. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: David S. Miller <davem@davemloft.net> (cherry picked from commit db10538) Signed-off-by: Jonathan Maple <jmaple@ciq.com> # Conflicts: # drivers/block/drbd/drbd_int.h # fs/cifs/transport.c # include/linux/tcp.h # net/ipv4/tcp.c
1 parent 71cf3b2 commit 0a970c6

File tree

1 file changed

+307
-0
lines changed

1 file changed

+307
-0
lines changed
Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
tcp: add tcp_sock_set_cork
2+
3+
jira LE-3571
4+
Rebuild_History Non-Buildable kernel-4.18.0-553.60.1.el8_10
5+
commit-author Christoph Hellwig <hch@lst.de>
6+
commit db10538a4b997a77a1fd561adaaa58afc7dcfa2f
7+
Empty-Commit: Cherry-Pick Conflicts during history rebuild.
8+
Will be included in final tarball splat. Ref for failed cherry-pick at:
9+
ciq/ciq_backports/kernel-4.18.0-553.60.1.el8_10/db10538a.failed
10+
11+
Add a helper to directly set the TCP_CORK sockopt from kernel space
12+
without going through a fake uaccess. Cleanup the callers to avoid
13+
pointless wrappers now that this is a simple function call.
14+
15+
Signed-off-by: Christoph Hellwig <hch@lst.de>
16+
Signed-off-by: David S. Miller <davem@davemloft.net>
17+
(cherry picked from commit db10538a4b997a77a1fd561adaaa58afc7dcfa2f)
18+
Signed-off-by: Jonathan Maple <jmaple@ciq.com>
19+
20+
# Conflicts:
21+
# drivers/block/drbd/drbd_int.h
22+
# fs/cifs/transport.c
23+
# include/linux/tcp.h
24+
# net/ipv4/tcp.c
25+
diff --cc drivers/block/drbd/drbd_int.h
26+
index dd0e1606fd7e,3550adc93c68..000000000000
27+
--- a/drivers/block/drbd/drbd_int.h
28+
+++ b/drivers/block/drbd/drbd_int.h
29+
@@@ -1574,17 -1570,10 +1574,24 @@@ extern void drbd_set_recv_tcq(struct dr
30+
extern void _drbd_clear_done_ee(struct drbd_device *device, struct list_head *to_be_freed);
31+
extern int drbd_connected(struct drbd_peer_device *);
32+
33+
++<<<<<<< HEAD
34+
+static inline void drbd_tcp_cork(struct socket *sock)
35+
+{
36+
+ int val = 1;
37+
+ (void) kernel_setsockopt(sock, SOL_TCP, TCP_CORK,
38+
+ (char*)&val, sizeof(val));
39+
+}
40+
+
41+
+static inline void drbd_tcp_uncork(struct socket *sock)
42+
+{
43+
+ int val = 0;
44+
+ (void) kernel_setsockopt(sock, SOL_TCP, TCP_CORK,
45+
++=======
46+
+ static inline void drbd_tcp_nodelay(struct socket *sock)
47+
+ {
48+
+ int val = 1;
49+
+ (void) kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY,
50+
++>>>>>>> db10538a4b99 (tcp: add tcp_sock_set_cork)
51+
(char*)&val, sizeof(val));
52+
}
53+
54+
diff --cc fs/cifs/transport.c
55+
index 81c73767363e,99760063e000..000000000000
56+
--- a/fs/cifs/transport.c
57+
+++ b/fs/cifs/transport.c
58+
@@@ -298,8 -324,7 +298,12 @@@ __smb_send_rqst(struct TCP_Server_Info
59+
sigset_t mask, oldmask;
60+
size_t total_len = 0, sent, size;
61+
struct socket *ssocket = server->ssocket;
62+
++<<<<<<< HEAD
63+
+ struct msghdr smb_msg = {};
64+
+ int val = 1;
65+
++=======
66+
+ struct msghdr smb_msg;
67+
++>>>>>>> db10538a4b99 (tcp: add tcp_sock_set_cork)
68+
__be32 rfc1002_marker;
69+
70+
if (cifs_rdma_enabled(server)) {
71+
diff --cc include/linux/tcp.h
72+
index 2f7a01dcf5ea,889eeb2256c2..000000000000
73+
--- a/include/linux/tcp.h
74+
+++ b/include/linux/tcp.h
75+
@@@ -543,9 -497,6 +543,13 @@@ static inline u16 tcp_mss_clamp(const s
76+
int tcp_skb_shift(struct sk_buff *to, struct sk_buff *from, int pcount,
77+
int shiftlen);
78+
79+
++<<<<<<< HEAD
80+
+int tcp_sock_set_keepidle_locked(struct sock *sk, int val);
81+
+int tcp_sock_set_keepidle(struct sock *sk, int val);
82+
+void tcp_sock_set_nodelay(struct sock *sk);
83+
+int tcp_sock_set_syncnt(struct sock *sk, int val);
84+
++=======
85+
+ void tcp_sock_set_cork(struct sock *sk, bool on);
86+
++>>>>>>> db10538a4b99 (tcp: add tcp_sock_set_cork)
87+
88+
#endif /* _LINUX_TCP_H */
89+
diff --cc net/ipv4/tcp.c
90+
index 19a03d7b55d2,e6cf702e16d6..000000000000
91+
--- a/net/ipv4/tcp.c
92+
+++ b/net/ipv4/tcp.c
93+
@@@ -2818,90 -2786,52 +2818,124 @@@ static int tcp_repair_options_est(struc
94+
return 0;
95+
}
96+
97+
-DEFINE_STATIC_KEY_FALSE(tcp_tx_delay_enabled);
98+
-EXPORT_SYMBOL(tcp_tx_delay_enabled);
99+
+/* TCP_NODELAY is weaker than TCP_CORK, so that this option on corked socket is
100+
+ * remembered, but it is not activated until cork is cleared.
101+
+ *
102+
+ * However, when TCP_NODELAY is set we make an explicit push, which overrides
103+
+ * even TCP_CORK for currently queued segments.
104+
+ */
105+
+static void __tcp_sock_set_nodelay(struct sock *sk, bool on)
106+
+{
107+
+ if (on) {
108+
+ tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF|TCP_NAGLE_PUSH;
109+
+ tcp_push_pending_frames(sk);
110+
+ } else {
111+
+ tcp_sk(sk)->nonagle &= ~TCP_NAGLE_OFF;
112+
+ }
113+
+}
114+
+
115+
++<<<<<<< HEAD
116+
+void tcp_sock_set_nodelay(struct sock *sk)
117+
+{
118+
+ lock_sock(sk);
119+
+ __tcp_sock_set_nodelay(sk, true);
120+
+ release_sock(sk);
121+
+}
122+
+EXPORT_SYMBOL(tcp_sock_set_nodelay);
123+
124+
-static void tcp_enable_tx_delay(void)
125+
+int tcp_sock_set_syncnt(struct sock *sk, int val)
126+
{
127+
- if (!static_branch_unlikely(&tcp_tx_delay_enabled)) {
128+
- static int __tcp_tx_delay_enabled = 0;
129+
+ if (val < 1 || val > MAX_TCP_SYNCNT)
130+
+ return -EINVAL;
131+
132+
- if (cmpxchg(&__tcp_tx_delay_enabled, 0, 1) == 0) {
133+
- static_branch_enable(&tcp_tx_delay_enabled);
134+
- pr_info("TCP_TX_DELAY enabled\n");
135+
- }
136+
+ lock_sock(sk);
137+
+ inet_csk(sk)->icsk_syn_retries = val;
138+
+ release_sock(sk);
139+
+ return 0;
140+
+}
141+
+EXPORT_SYMBOL(tcp_sock_set_syncnt);
142+
+
143+
+int tcp_sock_set_keepidle_locked(struct sock *sk, int val)
144+
+{
145+
+ struct tcp_sock *tp = tcp_sk(sk);
146+
+
147+
+ if (val < 1 || val > MAX_TCP_KEEPIDLE)
148+
+ return -EINVAL;
149+
+
150+
+ tp->keepalive_time = val * HZ;
151+
+ if (sock_flag(sk, SOCK_KEEPOPEN) &&
152+
+ !((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) {
153+
+ u32 elapsed = keepalive_time_elapsed(tp);
154+
+
155+
+ if (tp->keepalive_time > elapsed)
156+
+ elapsed = tp->keepalive_time - elapsed;
157+
+ else
158+
+ elapsed = 0;
159+
+ inet_csk_reset_keepalive_timer(sk, elapsed);
160+
}
161+
+
162+
+ return 0;
163+
}
164+
165+
+int tcp_sock_set_keepidle(struct sock *sk, int val)
166+
+{
167+
+ int err;
168+
+
169+
+ lock_sock(sk);
170+
+ err = tcp_sock_set_keepidle_locked(sk, val);
171+
+ release_sock(sk);
172+
+ return err;
173+
+}
174+
+EXPORT_SYMBOL(tcp_sock_set_keepidle);
175+
+
176+
+int tcp_set_window_clamp(struct sock *sk, int val)
177+
+{
178+
+ struct tcp_sock *tp = tcp_sk(sk);
179+
+
180+
+ if (!val) {
181+
+ if (sk->sk_state != TCP_CLOSE)
182+
+ return -EINVAL;
183+
+ tp->window_clamp = 0;
184+
+ } else {
185+
+ tp->window_clamp = val < SOCK_MIN_RCVBUF / 2 ?
186+
+ SOCK_MIN_RCVBUF / 2 : val;
187+
+ }
188+
+ return 0;
189+
+}
190+
+
191+
++=======
192+
+ /* When set indicates to always queue non-full frames. Later the user clears
193+
+ * this option and we transmit any pending partial frames in the queue. This is
194+
+ * meant to be used alongside sendfile() to get properly filled frames when the
195+
+ * user (for example) must write out headers with a write() call first and then
196+
+ * use sendfile to send out the data parts.
197+
+ *
198+
+ * TCP_CORK can be set together with TCP_NODELAY and it is stronger than
199+
+ * TCP_NODELAY.
200+
+ */
201+
+ static void __tcp_sock_set_cork(struct sock *sk, bool on)
202+
+ {
203+
+ struct tcp_sock *tp = tcp_sk(sk);
204+
+
205+
+ if (on) {
206+
+ tp->nonagle |= TCP_NAGLE_CORK;
207+
+ } else {
208+
+ tp->nonagle &= ~TCP_NAGLE_CORK;
209+
+ if (tp->nonagle & TCP_NAGLE_OFF)
210+
+ tp->nonagle |= TCP_NAGLE_PUSH;
211+
+ tcp_push_pending_frames(sk);
212+
+ }
213+
+ }
214+
+
215+
+ void tcp_sock_set_cork(struct sock *sk, bool on)
216+
+ {
217+
+ lock_sock(sk);
218+
+ __tcp_sock_set_cork(sk, on);
219+
+ release_sock(sk);
220+
+ }
221+
+ EXPORT_SYMBOL(tcp_sock_set_cork);
222+
+
223+
++>>>>>>> db10538a4b99 (tcp: add tcp_sock_set_cork)
224+
/*
225+
* Socket option code for TCP.
226+
*/
227+
* Unmerged path drivers/block/drbd/drbd_int.h
228+
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
229+
index 1c486b55de07..5725289429c6 100644
230+
--- a/drivers/block/drbd/drbd_receiver.c
231+
+++ b/drivers/block/drbd/drbd_receiver.c
232+
@@ -5974,7 +5974,7 @@ void drbd_send_acks_wf(struct work_struct *ws)
233+
rcu_read_unlock();
234+
235+
if (tcp_cork)
236+
- drbd_tcp_cork(connection->meta.socket);
237+
+ tcp_sock_set_cork(connection->meta.socket->sk, true);
238+
239+
err = drbd_finish_peer_reqs(device);
240+
kref_put(&device->kref, drbd_destroy_device);
241+
@@ -5987,7 +5987,7 @@ void drbd_send_acks_wf(struct work_struct *ws)
242+
}
243+
244+
if (tcp_cork)
245+
- drbd_tcp_uncork(connection->meta.socket);
246+
+ tcp_sock_set_cork(connection->meta.socket->sk, false);
247+
248+
return;
249+
}
250+
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
251+
index 1615be162131..a29ee3da8334 100644
252+
--- a/drivers/block/drbd/drbd_worker.c
253+
+++ b/drivers/block/drbd/drbd_worker.c
254+
@@ -2110,7 +2110,7 @@ static void wait_for_work(struct drbd_connection *connection, struct list_head *
255+
if (uncork) {
256+
mutex_lock(&connection->data.mutex);
257+
if (connection->data.socket)
258+
- drbd_tcp_uncork(connection->data.socket);
259+
+ tcp_sock_set_cork(connection->data.socket->sk, false);
260+
mutex_unlock(&connection->data.mutex);
261+
}
262+
263+
@@ -2165,9 +2165,9 @@ static void wait_for_work(struct drbd_connection *connection, struct list_head *
264+
mutex_lock(&connection->data.mutex);
265+
if (connection->data.socket) {
266+
if (cork)
267+
- drbd_tcp_cork(connection->data.socket);
268+
+ tcp_sock_set_cork(connection->data.socket->sk, true);
269+
else if (!uncork)
270+
- drbd_tcp_uncork(connection->data.socket);
271+
+ tcp_sock_set_cork(connection->data.socket->sk, false);
272+
}
273+
mutex_unlock(&connection->data.mutex);
274+
}
275+
* Unmerged path fs/cifs/transport.c
276+
* Unmerged path include/linux/tcp.h
277+
* Unmerged path net/ipv4/tcp.c
278+
diff --git a/net/rds/tcp_send.c b/net/rds/tcp_send.c
279+
index 7df869d37afd..2398e72a1263 100644
280+
--- a/net/rds/tcp_send.c
281+
+++ b/net/rds/tcp_send.c
282+
@@ -38,23 +38,18 @@
283+
#include "rds.h"
284+
#include "tcp.h"
285+
286+
-static void rds_tcp_cork(struct socket *sock, int val)
287+
-{
288+
- kernel_setsockopt(sock, SOL_TCP, TCP_CORK, (void *)&val, sizeof(val));
289+
-}
290+
-
291+
void rds_tcp_xmit_path_prepare(struct rds_conn_path *cp)
292+
{
293+
struct rds_tcp_connection *tc = cp->cp_transport_data;
294+
295+
- rds_tcp_cork(tc->t_sock, 1);
296+
+ tcp_sock_set_cork(tc->t_sock->sk, true);
297+
}
298+
299+
void rds_tcp_xmit_path_complete(struct rds_conn_path *cp)
300+
{
301+
struct rds_tcp_connection *tc = cp->cp_transport_data;
302+
303+
- rds_tcp_cork(tc->t_sock, 0);
304+
+ tcp_sock_set_cork(tc->t_sock->sk, false);
305+
}
306+
307+
/* the core send_sem serializes this with other xmit and shutdown */

0 commit comments

Comments
 (0)