mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-02-19 21:50:17 -05:00
mptcp: implement .splice_read
This patch implements .splice_read interface of mptcp struct proto_ops as mptcp_splice_read() with reference to tcp_splice_read(). Corresponding to __tcp_splice_read(), __mptcp_splice_read() is defined, invoking mptcp_read_sock() instead of tcp_read_sock(). mptcp_splice_read() is almost the same as tcp_splice_read(), except for sock_rps_record_flow(). Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn> Reviewed-by: Mat Martineau <martineau@kernel.org> Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org> Link: https://patch.msgid.link/20260130-net-next-mptcp-splice-v2-4-31332ba70d7f@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
2d85088d46
commit
22f3bd9bf8
@@ -4397,6 +4397,121 @@ static int mptcp_read_sock(struct sock *sk, read_descriptor_t *desc,
|
||||
return __mptcp_read_sock(sk, desc, recv_actor, false);
|
||||
}
|
||||
|
||||
static int __mptcp_splice_read(struct sock *sk, struct tcp_splice_state *tss)
|
||||
{
|
||||
/* Store TCP splice context information in read_descriptor_t. */
|
||||
read_descriptor_t rd_desc = {
|
||||
.arg.data = tss,
|
||||
.count = tss->len,
|
||||
};
|
||||
|
||||
return mptcp_read_sock(sk, &rd_desc, tcp_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.
|
||||
*
|
||||
* Return:
|
||||
* Amount of bytes that have been spliced.
|
||||
*
|
||||
**/
|
||||
static ssize_t mptcp_splice_read(struct socket *sock, loff_t *ppos,
|
||||
struct pipe_inode_info *pipe, size_t len,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct tcp_splice_state tss = {
|
||||
.pipe = pipe,
|
||||
.len = len,
|
||||
.flags = flags,
|
||||
};
|
||||
struct sock *sk = sock->sk;
|
||||
ssize_t spliced = 0;
|
||||
int ret = 0;
|
||||
long timeo;
|
||||
|
||||
/*
|
||||
* We can't seek on a socket input
|
||||
*/
|
||||
if (unlikely(*ppos))
|
||||
return -ESPIPE;
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
mptcp_rps_record_subflows(mptcp_sk(sk));
|
||||
|
||||
timeo = sock_rcvtimeo(sk, sock->file->f_flags & O_NONBLOCK);
|
||||
while (tss.len) {
|
||||
ret = __mptcp_splice_read(sk, &tss);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
} else if (!ret) {
|
||||
if (spliced)
|
||||
break;
|
||||
if (sock_flag(sk, SOCK_DONE))
|
||||
break;
|
||||
if (sk->sk_err) {
|
||||
ret = sock_error(sk);
|
||||
break;
|
||||
}
|
||||
if (sk->sk_shutdown & RCV_SHUTDOWN)
|
||||
break;
|
||||
if (sk->sk_state == TCP_CLOSE) {
|
||||
/*
|
||||
* This occurs when user tries to read
|
||||
* from never connected socket.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
tss.len -= ret;
|
||||
spliced += ret;
|
||||
|
||||
if (!tss.len || !timeo)
|
||||
break;
|
||||
release_sock(sk);
|
||||
lock_sock(sk);
|
||||
|
||||
if (sk->sk_err || sk->sk_state == TCP_CLOSE ||
|
||||
(sk->sk_shutdown & RCV_SHUTDOWN) ||
|
||||
signal_pending(current))
|
||||
break;
|
||||
}
|
||||
|
||||
release_sock(sk);
|
||||
|
||||
if (spliced)
|
||||
return spliced;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct proto_ops mptcp_stream_ops = {
|
||||
.family = PF_INET,
|
||||
.owner = THIS_MODULE,
|
||||
@@ -4418,6 +4533,7 @@ static const struct proto_ops mptcp_stream_ops = {
|
||||
.mmap = sock_no_mmap,
|
||||
.set_rcvlowat = mptcp_set_rcvlowat,
|
||||
.read_sock = mptcp_read_sock,
|
||||
.splice_read = mptcp_splice_read,
|
||||
};
|
||||
|
||||
static struct inet_protosw mptcp_protosw = {
|
||||
@@ -4523,6 +4639,7 @@ static const struct proto_ops mptcp_v6_stream_ops = {
|
||||
#endif
|
||||
.set_rcvlowat = mptcp_set_rcvlowat,
|
||||
.read_sock = mptcp_read_sock,
|
||||
.splice_read = mptcp_splice_read,
|
||||
};
|
||||
|
||||
static struct proto mptcp_v6_prot;
|
||||
|
||||
Reference in New Issue
Block a user