@@ -190,13 +190,6 @@ static bool __mptcp_move_skbs_from_subflow(struct mptcp_sock *msk,
return false;
}
- if (!(sk->sk_userlocks & SOCK_RCVBUF_LOCK)) {
- int rcvbuf = max(ssk->sk_rcvbuf, sk->sk_rcvbuf);
-
- if (rcvbuf > sk->sk_rcvbuf)
- sk->sk_rcvbuf = rcvbuf;
- }
-
tp = tcp_sk(ssk);
do {
u32 map_remaining, offset;
@@ -933,6 +926,25 @@ static bool __mptcp_move_skbs(struct mptcp_sock *msk)
return moved > 0;
}
+static void mptcp_rcv_space_adjust(struct mptcp_sock *msk)
+{
+ const struct mptcp_subflow_context *subflow;
+ struct sock *sk = (struct sock *)msk;
+ const struct sock *ssk;
+ int rcvbuf = 0;
+
+ if (sk->sk_userlocks & SOCK_RCVBUF_LOCK)
+ return;
+
+ mptcp_for_each_subflow(msk, subflow) {
+ ssk = mptcp_subflow_tcp_sock(subflow);
+ rcvbuf = max(ssk->sk_rcvbuf, rcvbuf);
+ }
+
+ if (rcvbuf)
+ sk->sk_rcvbuf = rcvbuf;
+}
+
static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
int nonblock, int flags, int *addr_len)
{
@@ -962,6 +974,8 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
__mptcp_flush_join_list(msk);
+ mptcp_rcv_space_adjust(msk);
+
while (len > (size_t)copied) {
int bytes_read;
@@ -975,8 +989,10 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
copied += bytes_read;
if (skb_queue_empty(&sk->sk_receive_queue) &&
- __mptcp_move_skbs(msk))
+ __mptcp_move_skbs(msk)) {
+ mptcp_rcv_space_adjust(msk);
continue;
+ }
/* only the master socket status is relevant here. The exit
* conditions mirror closely tcp_recvmsg()