@@ -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)))
@@ -1493,11 +1494,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->sched->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
@@ -1520,6 +1521,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))
@@ -1543,6 +1561,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;
@@ -1553,6 +1572,7 @@ static int __subflow_push_pending(struct sock *sk, struct sock *ssk,
}
info->sent += ret;
+ info->limit -= ret;
copied += ret;
len -= ret;
@@ -1617,7 +1637,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 */
@@ -1657,7 +1677,7 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk, bool
break;
}
msk->sched->last_snd = ssk;
- mptcp_update_first_pending(sk, &info);
+ mptcp_update_dfrags(sk, &info);
continue;
}
@@ -1687,7 +1707,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:
@@ -241,6 +241,7 @@ struct mptcp_data_frag {
u16 data_len;
u16 offset;
u16 overhead;
+ u16 sent;
u16 already_sent;
struct page *page;
};
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(-)