This patch adds a new member info_sent in struct mptcp_data_frag, save
info->sent in it, to support delay updating already_sent of dfrag until
all data are sent.
Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
net/mptcp/protocol.c | 34 +++++++++++++++++++++++++++-------
net/mptcp/protocol.h | 1 +
2 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index b1fef2b0c968..8ae8be76a09e 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1108,6 +1108,7 @@ mptcp_carve_data_frag(const struct mptcp_sock *msk, struct page_frag *pfrag,
dfrag->data_seq = msk->write_seq;
dfrag->overhead = offset - orig_offset + sizeof(struct mptcp_data_frag);
dfrag->offset = offset + sizeof(struct mptcp_data_frag);
+ dfrag->sent = 0;
dfrag->already_sent = 0;
dfrag->page = pfrag->page;
@@ -1243,8 +1244,8 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
pr_debug("msk=%p ssk=%p sending dfrag at seq=%llu len=%u already sent=%u",
msk, ssk, dfrag->data_seq, dfrag->data_len, info->sent);
- if (WARN_ON_ONCE(info->sent > info->limit ||
- info->limit > dfrag->data_len))
+ if (info->sent > info->limit ||
+ info->limit > dfrag->data_len)
return 0;
if (unlikely(!__tcp_can_send(ssk)))
@@ -1496,11 +1497,11 @@ static void mptcp_update_post_push(struct mptcp_sock *msk,
{
u64 snd_nxt_new = dfrag->data_seq;
- dfrag->already_sent += sent;
+ dfrag->sent += sent;
msk->snd_burst -= sent;
- snd_nxt_new += dfrag->already_sent;
+ snd_nxt_new += dfrag->sent;
/* snd_nxt_new can be smaller than snd_nxt in case mptcp
* is recovering after a failover. In that event, this re-sends
@@ -1523,6 +1524,23 @@ static void mptcp_update_first_pending(struct sock *sk, struct mptcp_sendmsg_inf
WRITE_ONCE(msk->first_pending, mptcp_next_frag(sk, info->last_frag));
}
+static void mptcp_update_dfrags(struct sock *sk, struct mptcp_sendmsg_info *info)
+{
+ struct mptcp_data_frag *dfrag = mptcp_send_head(sk);
+
+ if (!dfrag)
+ return;
+
+ do {
+ if (dfrag->sent) {
+ dfrag->already_sent = max(dfrag->already_sent, dfrag->sent);
+ dfrag->sent = 0;
+ }
+ } while ((dfrag = mptcp_next_frag(sk, dfrag)));
+
+ mptcp_update_first_pending(sk, info);
+}
+
void mptcp_check_and_set_pending(struct sock *sk)
{
if (mptcp_send_head(sk))
@@ -1546,6 +1564,7 @@ static int __subflow_push_pending(struct sock *sk, struct sock *ssk,
info->sent = dfrag->already_sent;
info->limit = dfrag->data_len;
len = dfrag->data_len - dfrag->already_sent;
+ dfrag->sent = info->sent;
while (len > 0) {
int ret = 0;
@@ -1556,6 +1575,7 @@ static int __subflow_push_pending(struct sock *sk, struct sock *ssk,
}
info->sent += ret;
+ info->limit -= ret;
copied += ret;
len -= ret;
@@ -1619,7 +1639,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
mptcp_subflow_set_scheduled(subflow, false);
}
}
- mptcp_update_first_pending(sk, &info);
+ mptcp_update_dfrags(sk, &info);
}
/* at this point we held the socket lock for the last subflow we used */
@@ -1658,7 +1678,7 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk, bool
goto again;
break;
}
- mptcp_update_first_pending(sk, &info);
+ mptcp_update_dfrags(sk, &info);
continue;
}
@@ -1686,7 +1706,7 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk, bool
mptcp_subflow_set_scheduled(subflow, false);
}
}
- mptcp_update_first_pending(sk, &info);
+ mptcp_update_dfrags(sk, &info);
}
out:
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 118fe5a2745c..f60520bfdb7d 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -242,6 +242,7 @@ struct mptcp_data_frag {
u16 data_len;
u16 offset;
u16 overhead;
+ u16 sent;
u16 already_sent;
struct page *page;
};
--
2.35.3