kcm: Support MSG_SPLICE_PAGES
Make AF_KCM sendmsg() support MSG_SPLICE_PAGES. This causes pages to be spliced from the source iterator if possible. 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: Tom Herbert <tom@herbertland.com> cc: Tom Herbert <tom@quantonium.net> cc: Cong Wang <cong.wang@bytedance.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
28cfea989d
commit
2b03bcae66
@ -989,29 +989,52 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
|
|||||||
merge = false;
|
merge = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
copy = min_t(int, msg_data_left(msg),
|
if (msg->msg_flags & MSG_SPLICE_PAGES) {
|
||||||
pfrag->size - pfrag->offset);
|
copy = msg_data_left(msg);
|
||||||
|
if (!sk_wmem_schedule(sk, copy))
|
||||||
|
goto wait_for_memory;
|
||||||
|
|
||||||
if (!sk_wmem_schedule(sk, copy))
|
err = skb_splice_from_iter(skb, &msg->msg_iter, copy,
|
||||||
goto wait_for_memory;
|
sk->sk_allocation);
|
||||||
|
if (err < 0) {
|
||||||
|
if (err == -EMSGSIZE)
|
||||||
|
goto wait_for_memory;
|
||||||
|
goto out_error;
|
||||||
|
}
|
||||||
|
|
||||||
err = skb_copy_to_page_nocache(sk, &msg->msg_iter, skb,
|
copy = err;
|
||||||
pfrag->page,
|
skb_shinfo(skb)->flags |= SKBFL_SHARED_FRAG;
|
||||||
pfrag->offset,
|
sk_wmem_queued_add(sk, copy);
|
||||||
copy);
|
sk_mem_charge(sk, copy);
|
||||||
if (err)
|
|
||||||
goto out_error;
|
|
||||||
|
|
||||||
/* Update the skb. */
|
if (head != skb)
|
||||||
if (merge) {
|
head->truesize += copy;
|
||||||
skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy);
|
|
||||||
} else {
|
} else {
|
||||||
skb_fill_page_desc(skb, i, pfrag->page,
|
copy = min_t(int, msg_data_left(msg),
|
||||||
pfrag->offset, copy);
|
pfrag->size - pfrag->offset);
|
||||||
get_page(pfrag->page);
|
if (!sk_wmem_schedule(sk, copy))
|
||||||
|
goto wait_for_memory;
|
||||||
|
|
||||||
|
err = skb_copy_to_page_nocache(sk, &msg->msg_iter, skb,
|
||||||
|
pfrag->page,
|
||||||
|
pfrag->offset,
|
||||||
|
copy);
|
||||||
|
if (err)
|
||||||
|
goto out_error;
|
||||||
|
|
||||||
|
/* Update the skb. */
|
||||||
|
if (merge) {
|
||||||
|
skb_frag_size_add(
|
||||||
|
&skb_shinfo(skb)->frags[i - 1], copy);
|
||||||
|
} else {
|
||||||
|
skb_fill_page_desc(skb, i, pfrag->page,
|
||||||
|
pfrag->offset, copy);
|
||||||
|
get_page(pfrag->page);
|
||||||
|
}
|
||||||
|
|
||||||
|
pfrag->offset += copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
pfrag->offset += copy;
|
|
||||||
copied += copy;
|
copied += copy;
|
||||||
if (head != skb) {
|
if (head != skb) {
|
||||||
head->len += copy;
|
head->len += copy;
|
||||||
|
Loading…
Reference in New Issue
Block a user