Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions include/linux/skmsg.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,16 @@ int sk_msg_memcopy_from_iter(struct sock *sk, struct iov_iter *from,
struct sk_msg *msg, u32 bytes);
int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
int len, int flags);
int __sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
int len, int flags, int *copied_from_self);
typedef int (*sk_msg_read_actor_t)(void *arg, struct page *page,
unsigned int offset, size_t len);
/* Core function for reading ingress_msg, dispatches to the given actor */
int sk_msg_read_core(struct sock *sk, struct sk_psock *psock,
size_t len, int flags,
sk_msg_read_actor_t actor, void *actor_arg,
int *copied_from_self);
int sk_msg_recvmsg_actor(void *arg, struct page *page,
unsigned int offset, size_t len);

bool sk_msg_is_readable(struct sock *sk);

static inline void sk_msg_check_to_free(struct sk_msg *msg, u32 i, u32 bytes)
Expand Down
3 changes: 3 additions & 0 deletions include/net/inet_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ void __inet_accept(struct socket *sock, struct socket *newsock,
struct sock *newsk);
int inet_send_prepare(struct sock *sk);
int inet_sendmsg(struct socket *sock, struct msghdr *msg, size_t size);
ssize_t inet_splice_read(struct socket *sock, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len,
unsigned int flags);
void inet_splice_eof(struct socket *sock);
int inet_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
int flags);
Expand Down
3 changes: 3 additions & 0 deletions include/net/sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -1317,6 +1317,9 @@ struct proto {
size_t len);
int (*recvmsg)(struct sock *sk, struct msghdr *msg,
size_t len, int flags, int *addr_len);
ssize_t (*splice_read)(struct socket *sock, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len,
unsigned int flags);
void (*splice_eof)(struct socket *sock);
int (*bind)(struct sock *sk,
struct sockaddr_unsized *addr, int addr_len);
Expand Down
34 changes: 29 additions & 5 deletions net/core/skmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,10 +409,12 @@ int sk_msg_memcopy_from_iter(struct sock *sk, struct iov_iter *from,
}
EXPORT_SYMBOL_GPL(sk_msg_memcopy_from_iter);

int __sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
int len, int flags, int *copied_from_self)
/* Core function for reading ingress_msg, dispatches to the given actor */
int sk_msg_read_core(struct sock *sk, struct sk_psock *psock,
size_t len, int flags,
sk_msg_read_actor_t actor, void *actor_arg,
int *copied_from_self)
{
struct iov_iter *iter = &msg->msg_iter;
int peek = flags & MSG_PEEK;
struct sk_msg *msg_rx;
int i, copied = 0;
Expand Down Expand Up @@ -440,8 +442,19 @@ int __sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg
if (copied + copy > len)
copy = len - copied;
if (copy)
copy = copy_page_to_iter(page, sge->offset, copy, iter);
copy = actor(actor_arg, page,
sge->offset, copy);
if (!copy) {
/*
* The loop processes msg_rx->sg entries
* sequentially and prior entries may
* already be consumed. Advance sg.start
* so the next call resumes at the correct
* entry, otherwise it would revisit
* zero-length entries and return -EFAULT.
*/
if (!peek)
msg_rx->sg.start = i;
copied = copied ? copied : -EFAULT;
goto out;
}
Expand Down Expand Up @@ -495,12 +508,23 @@ int __sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg
out:
return copied;
}
EXPORT_SYMBOL_GPL(sk_msg_read_core);

int sk_msg_recvmsg_actor(void *arg, struct page *page,
unsigned int offset, size_t len)
{
struct msghdr *msg = arg;

return copy_page_to_iter(page, offset, len, &msg->msg_iter);
}
EXPORT_SYMBOL_GPL(sk_msg_recvmsg_actor);

/* Receive sk_msg from psock->ingress_msg to @msg. */
int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
int len, int flags)
{
return __sk_msg_recvmsg(sk, psock, msg, len, flags, NULL);
return sk_msg_read_core(sk, psock, len, flags,
sk_msg_recvmsg_actor, msg, NULL);
}
EXPORT_SYMBOL_GPL(sk_msg_recvmsg);

Expand Down
15 changes: 14 additions & 1 deletion net/ipv4/af_inet.c
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,19 @@ void inet_splice_eof(struct socket *sock)
}
EXPORT_SYMBOL_GPL(inet_splice_eof);

ssize_t inet_splice_read(struct socket *sock, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len,
unsigned int flags)
{
struct sock *sk = sock->sk;
const struct proto *prot;

prot = READ_ONCE(sk->sk_prot);
return INDIRECT_CALL_1(prot->splice_read, tcp_splice_read, sock,
ppos, pipe, len, flags);
}
EXPORT_SYMBOL_GPL(inet_splice_read);

INDIRECT_CALLABLE_DECLARE(int udp_recvmsg(struct sock *, struct msghdr *,
size_t, int, int *));
int inet_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
Expand Down Expand Up @@ -1079,7 +1092,7 @@ const struct proto_ops inet_stream_ops = {
.mmap = tcp_mmap,
#endif
.splice_eof = inet_splice_eof,
.splice_read = tcp_splice_read,
.splice_read = inet_splice_read,
.set_peek_off = sk_set_peek_off,
.read_sock = tcp_read_sock,
.read_skb = tcp_read_skb,
Expand Down
Loading
Loading