mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 16:44:58 +02:00
af_unix: Support MSG_SPLICE_PAGES
Make AF_UNIX sendmsg() support MSG_SPLICE_PAGES, splicing in pages from the source iterator if possible and copying the data in otherwise. This allows ->sendpage() to be replaced by something that can handle multiple multipage folios in a single transaction. Signed-off-by: David Howells <dhowells@redhat.com> cc: Kuniyuki Iwashima <kuniyu@amazon.com> cc: Jens Axboe <axboe@kernel.dk> cc: Matthew Wilcox <willy@infradead.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
c49cf26632
commit
a0dbf5f818
|
|
@ -2200,6 +2200,11 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
|
||||||
while (sent < len) {
|
while (sent < len) {
|
||||||
size = len - sent;
|
size = len - sent;
|
||||||
|
|
||||||
|
if (unlikely(msg->msg_flags & MSG_SPLICE_PAGES)) {
|
||||||
|
skb = sock_alloc_send_pskb(sk, 0, 0,
|
||||||
|
msg->msg_flags & MSG_DONTWAIT,
|
||||||
|
&err, 0);
|
||||||
|
} else {
|
||||||
/* Keep two messages in the pipe so it schedules better */
|
/* Keep two messages in the pipe so it schedules better */
|
||||||
size = min_t(int, size, (sk->sk_sndbuf >> 1) - 64);
|
size = min_t(int, size, (sk->sk_sndbuf >> 1) - 64);
|
||||||
|
|
||||||
|
|
@ -2213,6 +2218,7 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
|
||||||
skb = sock_alloc_send_pskb(sk, size - data_len, data_len,
|
skb = sock_alloc_send_pskb(sk, size - data_len, data_len,
|
||||||
msg->msg_flags & MSG_DONTWAIT, &err,
|
msg->msg_flags & MSG_DONTWAIT, &err,
|
||||||
get_order(UNIX_SKB_FRAGS_SZ));
|
get_order(UNIX_SKB_FRAGS_SZ));
|
||||||
|
}
|
||||||
if (!skb)
|
if (!skb)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
|
||||||
|
|
@ -2224,6 +2230,16 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
|
||||||
}
|
}
|
||||||
fds_sent = true;
|
fds_sent = true;
|
||||||
|
|
||||||
|
if (unlikely(msg->msg_flags & MSG_SPLICE_PAGES)) {
|
||||||
|
err = skb_splice_from_iter(skb, &msg->msg_iter, size,
|
||||||
|
sk->sk_allocation);
|
||||||
|
if (err < 0) {
|
||||||
|
kfree_skb(skb);
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
size = err;
|
||||||
|
refcount_add(size, &sk->sk_wmem_alloc);
|
||||||
|
} else {
|
||||||
skb_put(skb, size - data_len);
|
skb_put(skb, size - data_len);
|
||||||
skb->data_len = data_len;
|
skb->data_len = data_len;
|
||||||
skb->len = size;
|
skb->len = size;
|
||||||
|
|
@ -2232,6 +2248,7 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unix_state_lock(other);
|
unix_state_lock(other);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user