Skip to content

Commit 65bada8

Browse files
isilencekuba-moo
authored andcommitted
net: add callback for setting a ubuf_info to skb
At the moment an skb can only have one ubuf_info associated with it, which might be a performance problem for zerocopy sends in cases like TCP via io_uring. Add a callback for assigning ubuf_info to skb, this way we will implement smarter assignment later like linking ubuf_info together. Note, it's an optional callback, which should be compatible with skb_zcopy_set(), that's because the net stack might potentially decide to clone an skb and take another reference to ubuf_info whenever it wishes. Also, a correct implementation should always be able to bind to an skb without prior ubuf_info, otherwise we could end up in a situation when the send would not be able to progress. Reviewed-by: Jens Axboe <[email protected]> Reviewed-by: David Ahern <[email protected]> Signed-off-by: Pavel Begunkov <[email protected]> Reviewed-by: Willem de Bruijn <[email protected]> Link: https://lore.kernel.org/all/b7918aadffeb787c84c9e72e34c729dc04f3a45d.1713369317.git.asml.silence@gmail.com Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 7ab4f16 commit 65bada8

File tree

2 files changed

+16
-6
lines changed

2 files changed

+16
-6
lines changed

include/linux/skbuff.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,8 @@ enum {
530530
struct ubuf_info_ops {
531531
void (*complete)(struct sk_buff *, struct ubuf_info *,
532532
bool zerocopy_success);
533+
/* has to be compatible with skb_zcopy_set() */
534+
int (*link_skb)(struct sk_buff *skb, struct ubuf_info *uarg);
533535
};
534536

535537
/*

net/core/skbuff.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1880,11 +1880,18 @@ int skb_zerocopy_iter_stream(struct sock *sk, struct sk_buff *skb,
18801880
struct ubuf_info *orig_uarg = skb_zcopy(skb);
18811881
int err, orig_len = skb->len;
18821882

1883-
/* An skb can only point to one uarg. This edge case happens when
1884-
* TCP appends to an skb, but zerocopy_realloc triggered a new alloc.
1885-
*/
1886-
if (orig_uarg && uarg != orig_uarg)
1887-
return -EEXIST;
1883+
if (uarg->ops->link_skb) {
1884+
err = uarg->ops->link_skb(skb, uarg);
1885+
if (err)
1886+
return err;
1887+
} else {
1888+
/* An skb can only point to one uarg. This edge case happens
1889+
* when TCP appends to an skb, but zerocopy_realloc triggered
1890+
* a new alloc.
1891+
*/
1892+
if (orig_uarg && uarg != orig_uarg)
1893+
return -EEXIST;
1894+
}
18881895

18891896
err = __zerocopy_sg_from_iter(msg, sk, skb, &msg->msg_iter, len);
18901897
if (err == -EFAULT || (err == -EMSGSIZE && skb->len == orig_len)) {
@@ -1898,7 +1905,8 @@ int skb_zerocopy_iter_stream(struct sock *sk, struct sk_buff *skb,
18981905
return err;
18991906
}
19001907

1901-
skb_zcopy_set(skb, uarg, NULL);
1908+
if (!uarg->ops->link_skb)
1909+
skb_zcopy_set(skb, uarg, NULL);
19021910
return skb->len - orig_len;
19031911
}
19041912
EXPORT_SYMBOL_GPL(skb_zerocopy_iter_stream);

0 commit comments

Comments
 (0)