From: Geliang Tang <geliang@kernel.org>
To: Paolo Abeni <pabeni@redhat.com>, mptcp@lists.linux.dev, hare@kernel.org
Cc: Geliang Tang <tanggeliang@kylinos.cn>
Subject: Re: [PATCH mptcp-next v7 3/4] mptcp: implement .splice_read
Date: Thu, 10 Jul 2025 17:10:44 +0800 [thread overview]
Message-ID: <0346b37ff8021446d3be6839132141daf277ffb6.camel@kernel.org> (raw)
In-Reply-To: <63354366-79aa-4799-9af3-5f5a379ea4eb@redhat.com>
Hi Paolo,
On Tue, 2025-07-08 at 16:52 +0200, Paolo Abeni wrote:
> On 7/7/25 11:34 AM, Geliang Tang wrote:
> > From: Geliang Tang <tanggeliang@kylinos.cn>
> >
> > This patch implements .splice_read interface of mptcp struct
> > proto_ops
> > as mptcp_splice_read() with reference to tcp_splice_read().
> >
> > Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
> > ---
> > net/mptcp/protocol.c | 136
> > +++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 136 insertions(+)
> >
> > diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> > index fc429d175ede..4638d4be2b98 100644
> > --- a/net/mptcp/protocol.c
> > +++ b/net/mptcp/protocol.c
> > @@ -4023,6 +4023,140 @@ static int mptcp_read_sock(struct sock *sk,
> > read_descriptor_t *desc,
> > return copied;
> > }
> >
> > +/*
> > + * MPTCP splice context
> > + */
> > +struct mptcp_splice_state {
> > + struct pipe_inode_info *pipe;
> > + size_t len;
> > + unsigned int flags;
> > +};
> > +
> > +static int mptcp_splice_data_recv(read_descriptor_t *rd_desc,
> > struct sk_buff *skb,
> > + unsigned int offset, size_t len)
> > +{
> > + struct mptcp_splice_state *mss = rd_desc->arg.data;
> > + int ret;
> > +
> > + ret = skb_splice_bits(skb, skb->sk, offset, mss->pipe,
> > + min(rd_desc->count, len), mss-
> > >flags);
> > + if (ret > 0)
> > + rd_desc->count -= ret;
> > + return ret;
> > +}
>
> I have mixed feeling WRT the above. I'm wondering if we should reuse
> the
> same code already existing in TCP, moving tcp_spice_state definition
> in
> some shared hdr and macking tcp_splice_data_recv not static.
>
> > +static int __mptcp_splice_read(struct sock *sk, struct
> > mptcp_splice_state *mss)
> > +{
> > + /* Store MPTCP splice context information in
> > read_descriptor_t. */
> > + read_descriptor_t rd_desc = {
> > + .arg.data = mss,
> > + .count = mss->len,
> > + };
> > +
> > + return mptcp_read_sock(sk, &rd_desc,
> > mptcp_splice_data_recv);
> > +}
> > +
> > +/**
> > + * mptcp_splice_read - splice data from MPTCP socket to a pipe
> > + * @sock: socket to splice from
> > + * @ppos: position (not valid)
> > + * @pipe: pipe to splice to
> > + * @len: number of bytes to splice
> > + * @flags: splice modifier flags
> > + *
> > + * Description:
> > + * Will read pages from given socket and fill them into a pipe.
> > + *
> > + **/
> > +static ssize_t mptcp_splice_read(struct socket *sock, loff_t
> > *ppos,
> > + struct pipe_inode_info *pipe,
> > size_t len,
> > + unsigned int flags)
> > +{
> > + struct mptcp_splice_state mss = {
> > + .pipe = pipe,
> > + .len = len,
> > + .flags = flags,
> > + };
> > + struct sock *sk = sock->sk;
> > + ssize_t spliced;
> > + long timeo;
> > + int ret;
> > +
> > + /*
> > + * We can't seek on a socket input
> > + */
> > + if (unlikely(*ppos))
> > + return -ESPIPE;
> > +
> > + spliced = 0;
> > + ret = 0;
> > +
> > + lock_sock(sk);
> > +
> > + timeo = sock_rcvtimeo(sk, sock->file->f_flags &
> > O_NONBLOCK);
> > + while (mss.len) {
> > + ret = __mptcp_splice_read(sk, &mss);
> > + if (ret < 0) {
> > + break;
> > + } else if (!ret) {
> > + if (spliced)
> > + break;
> > + if (sock_flag(sk, SOCK_DONE))
> > + break;
I noticed that this SOCK_DONE flag is also checked in
tcp_recvmsg_locked() but not in mptcp_recvmsg(). I wonder if this flag
should also be checked in mptcp_recvmsg() too.
> > + if (sk->sk_err) {
> > + ret = sock_error(sk);
> > + break;
> > + }
> > + if (sk->sk_shutdown & RCV_SHUTDOWN) {
> > + if (__mptcp_move_skbs(sk))
> > + continue;
> > + break;
> > + }
> > + if (sk->sk_state == TCP_CLOSE) {
> > + ret = -ENOTCONN;
> > + break;
> > + }
> > + if (!timeo) {
> > + ret = -EAGAIN;
> > + break;
> > + }
> > + /* if __mptcp_splice_read() got nothing
> > while we have
> > + * an skb in receive queue, we do not want
> > to loop.
> > + * This might happen with URG data.
> > + */
> > + if (!skb_queue_empty(&sk-
> > >sk_receive_queue))
> > + break;
> > + ret = sk_wait_data(sk, &timeo, NULL);
> > + if (ret < 0)
> > + break;
> > + if (signal_pending(current)) {
> > + ret = sock_intr_errno(timeo);
> > + break;
> > + }
>
> I think that moving the above if statement before the queue empty
> check
> will not change the overall behavior.
>
> With that in place you could factor out an
>
> bool mptcp_recv_should_stop(struct sock *sk, int err)
This helper can also be used in tcp_recvmsg_locked and tcp_splice_read
too. What about rename it as tcp_recv_should_stop, then add it in
include/net/tcp.h and use it for both TCP and MPTCP. WDYT?
Thanks,
-Geliang
>
> helper from mptcp_recvmsg() and use it verbatim in both in
> mptcp_recvmsg() and here.
>
> Side note: suggestions for a better helper name welcome!
>
> /P
>
next prev parent reply other threads:[~2025-07-10 9:10 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-07 9:34 [PATCH mptcp-next v7 0/4] implement mptcp read_sock Geliang Tang
2025-07-07 9:34 ` [PATCH mptcp-next v7 1/4] mptcp: add eat_recv_skb helper Geliang Tang
2025-07-07 9:34 ` [PATCH mptcp-next v7 2/4] mptcp: implement .read_sock Geliang Tang
2025-07-08 16:16 ` Matthieu Baerts
2025-07-07 9:34 ` [PATCH mptcp-next v7 3/4] mptcp: implement .splice_read Geliang Tang
2025-07-08 14:52 ` Paolo Abeni
2025-07-10 9:10 ` Geliang Tang [this message]
2025-07-07 9:34 ` [PATCH mptcp-next v7 4/4] selftests: mptcp: add splice io mode Geliang Tang
2025-07-08 16:23 ` Matthieu Baerts
2025-07-08 15:25 ` [PATCH mptcp-next v7 0/4] implement mptcp read_sock MPTCP CI
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=0346b37ff8021446d3be6839132141daf277ffb6.camel@kernel.org \
--to=geliang@kernel.org \
--cc=hare@kernel.org \
--cc=mptcp@lists.linux.dev \
--cc=pabeni@redhat.com \
--cc=tanggeliang@kylinos.cn \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.