Commit be12a1fe authored by Hannes Frederic Sowa's avatar Hannes Frederic Sowa Committed by David S. Miller

net: skbuff: add skb_append_pagefrags and use it

Signed-off-by: default avatarHannes Frederic Sowa <hannes@stressinduktion.org>
Acked-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d98c3edc
...@@ -861,6 +861,9 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, ...@@ -861,6 +861,9 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
int len, int odd, struct sk_buff *skb), int len, int odd, struct sk_buff *skb),
void *from, int length); void *from, int length);
int skb_append_pagefrags(struct sk_buff *skb, struct page *page,
int offset, size_t size);
struct skb_seq_state { struct skb_seq_state {
__u32 lower_offset; __u32 lower_offset;
__u32 upper_offset; __u32 upper_offset;
......
...@@ -2915,6 +2915,24 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, ...@@ -2915,6 +2915,24 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
} }
EXPORT_SYMBOL(skb_append_datato_frags); EXPORT_SYMBOL(skb_append_datato_frags);
int skb_append_pagefrags(struct sk_buff *skb, struct page *page,
int offset, size_t size)
{
int i = skb_shinfo(skb)->nr_frags;
if (skb_can_coalesce(skb, i, page, offset)) {
skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], size);
} else if (i < MAX_SKB_FRAGS) {
get_page(page);
skb_fill_page_desc(skb, i, page, offset, size);
} else {
return -EMSGSIZE;
}
return 0;
}
EXPORT_SYMBOL_GPL(skb_append_pagefrags);
/** /**
* skb_pull_rcsum - pull skb and update receive checksum * skb_pull_rcsum - pull skb and update receive checksum
* @skb: buffer to update * @skb: buffer to update
......
...@@ -1233,11 +1233,9 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page, ...@@ -1233,11 +1233,9 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
} }
while (size > 0) { while (size > 0) {
int i; if (skb_is_gso(skb)) {
if (skb_is_gso(skb))
len = size; len = size;
else { } else {
/* Check if the remaining data fits into current packet. */ /* Check if the remaining data fits into current packet. */
len = mtu - skb->len; len = mtu - skb->len;
...@@ -1289,15 +1287,10 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page, ...@@ -1289,15 +1287,10 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
continue; continue;
} }
i = skb_shinfo(skb)->nr_frags;
if (len > size) if (len > size)
len = size; len = size;
if (skb_can_coalesce(skb, i, page, offset)) {
skb_frag_size_add(&skb_shinfo(skb)->frags[i-1], len); if (skb_append_pagefrags(skb, page, offset, len)) {
} else if (i < MAX_SKB_FRAGS) {
get_page(page);
skb_fill_page_desc(skb, i, page, offset, len);
} else {
err = -EMSGSIZE; err = -EMSGSIZE;
goto error; goto error;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment