All of lore.kernel.org
 help / color / mirror / Atom feed
* [MPTCP] [PATCH mptcp-next 3/7] mptcp: avoid blocking in tcp_sendpages due to skb alloc
@ 2020-05-06 13:02 Florian Westphal
  0 siblings, 0 replies; only message in thread
From: Florian Westphal @ 2020-05-06 13:02 UTC (permalink / raw)
  To: mptcp

[-- Attachment #1: Type: text/plain, Size: 2895 bytes --]

If memory is tight, tcp_sendpages may fail because it can't
allocate the skb head.

Now that we pass DONTWAIT to tcp_sendpages it won't block anymore on the
subflow socket when this happens.

We can avoid such allocation failure in tcp code by preallocating an skb
skb when we pick the subflow to use.

If it fails, we can wait on the mptcp socket until memory becomes
available.

Suggested-by: Paolo Abeni <pabeni(a)redhat.com>
Signed-off-by: Florian Westphal <fw(a)strlen.de>
---
 net/mptcp/protocol.c | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index ab6599dfda59..f28c131c010e 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -488,6 +488,22 @@ mptcp_carve_data_frag(const struct mptcp_sock *msk, struct page_frag *pfrag,
 	return dfrag;
 }
 
+static bool mptcp_sendmsg_alloc_skb(struct sock *sk)
+{
+	struct sk_buff *skb;
+
+	if (sk->sk_tx_skb_cache)
+		return true;
+
+	skb = alloc_skb_fclone(sk->sk_prot->max_header, sk->sk_allocation);
+	if (skb) {
+		skb_reserve(skb, sk->sk_prot->max_header);
+		sk->sk_tx_skb_cache = skb;
+	}
+
+	return sk->sk_tx_skb_cache != NULL;
+}
+
 static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
 			      struct msghdr *msg, struct mptcp_data_frag *dfrag,
 			      long *timeo, int *pmss_now,
@@ -504,6 +520,11 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
 	u64 *write_seq;
 	size_t psize;
 
+	if (!ssk->sk_tx_skb_cache) {
+		ssk->sk_tx_skb_cache = sk->sk_tx_skb_cache;
+		sk->sk_tx_skb_cache = NULL;
+	}
+
 	/* use the mptcp page cache so that we can easily move the data
 	 * from one substream to another, but do per subflow memory accounting
 	 * Note: pfrag is used only !retransmission, but the compiler if
@@ -656,9 +677,13 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
 static struct sock *mptcp_subflow_get_send(struct mptcp_sock *msk)
 {
 	struct mptcp_subflow_context *subflow;
+	struct sock *sk = (struct sock *)msk;
 	struct sock *backup = NULL;
 
-	sock_owned_by_me((const struct sock *)msk);
+	sock_owned_by_me(sk);
+
+	if (!mptcp_sendmsg_alloc_skb(sk))
+		return NULL;
 
 	mptcp_for_each_subflow(msk, subflow) {
 		struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
@@ -1478,6 +1503,7 @@ static void mptcp_destroy(struct sock *sk)
 	if (msk->cached_ext)
 		__skb_ext_put(msk->cached_ext);
 
+	kfree_skb(sk->sk_tx_skb_cache);
 	sk_sockets_allocated_dec(sk);
 }
 
@@ -1688,6 +1714,7 @@ static struct proto mptcp_prot = {
 	.hash		= inet_hash,
 	.unhash		= inet_unhash,
 	.get_port	= mptcp_get_port,
+	.max_header	= MAX_TCP_HEADER,
 	.sockets_allocated	= &mptcp_sockets_allocated,
 	.memory_allocated	= &tcp_memory_allocated,
 	.memory_pressure	= &tcp_memory_pressure,
-- 
2.26.2

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2020-05-06 13:02 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-06 13:02 [MPTCP] [PATCH mptcp-next 3/7] mptcp: avoid blocking in tcp_sendpages due to skb alloc Florian Westphal

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.