Skip to content

Commit

Permalink
net: splice: avoid high order page splitting
Browse files Browse the repository at this point in the history
splice() can handle pages of any order, but network code tries hard to
split them in PAGE_SIZE units. Not quite successfully anyway, as
__splice_segment() assumed poff < PAGE_SIZE. This is true for
the skb->data part, not necessarily for the fragments.

This patch removes this logic to give the pages as they are in the skb.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Willy Tarreau <w@1wt.eu>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Eric Dumazet authored and David S. Miller committed Jan 21, 2013
1 parent b74aa93 commit 82bda61
Showing 1 changed file with 9 additions and 29 deletions.
38 changes: 9 additions & 29 deletions net/core/skbuff.c
Original file line number Diff line number Diff line change
Expand Up @@ -1706,27 +1706,15 @@ static bool spd_fill_page(struct splice_pipe_desc *spd,
return false;
}

static inline void __segment_seek(struct page **page, unsigned int *poff,
unsigned int *plen, unsigned int off)
{
unsigned long n;

*poff += off;
n = *poff / PAGE_SIZE;
if (n)
*page = nth_page(*page, n);

*poff = *poff % PAGE_SIZE;
*plen -= off;
}

static bool __splice_segment(struct page *page, unsigned int poff,
unsigned int plen, unsigned int *off,
unsigned int *len, struct sk_buff *skb,
struct splice_pipe_desc *spd, bool linear,
struct sock *sk,
struct pipe_inode_info *pipe)
{
unsigned int flen;

if (!*len)
return true;

Expand All @@ -1737,24 +1725,16 @@ static bool __splice_segment(struct page *page, unsigned int poff,
}

/* ignore any bits we already processed */
if (*off) {
__segment_seek(&page, &poff, &plen, *off);
*off = 0;
}

do {
unsigned int flen = min(*len, plen);
poff += *off;
plen -= *off;
*off = 0;

/* the linear region may spread across several pages */
flen = min_t(unsigned int, flen, PAGE_SIZE - poff);
flen = min(*len, plen);

if (spd_fill_page(spd, pipe, page, &flen, poff, skb, linear, sk))
return true;

__segment_seek(&page, &poff, &plen, flen);
*len -= flen;
if (spd_fill_page(spd, pipe, page, &flen, poff, skb, linear, sk))
return true;

} while (*len && plen);
*len -= flen;

return false;
}
Expand Down

0 comments on commit 82bda61

Please sign in to comment.