Skip to content

Commit 09c2c90

Browse files
edumazetkuba-moo
authored andcommitted
net: allow alloc_skb_with_frags() to allocate bigger packets
Refactor alloc_skb_with_frags() to allow bigger packets allocations. Instead of assuming that only order-0 allocations will be attempted, use the caller supplied max order. v2: try harder to use high-order pages, per Willem feedback. Link: https://lore.kernel.org/netdev/CANn89iJQfmc_KeUr3TeXvsLQwo3ZymyoCr7Y6AnHrkWSuz0yAg@mail.gmail.com/ Signed-off-by: Eric Dumazet <[email protected]> Cc: Tahsin Erdogan <[email protected]> Reviewed-by: Willem de Bruijn <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 49c467d commit 09c2c90

File tree

1 file changed

+25
-31
lines changed

1 file changed

+25
-31
lines changed

net/core/skbuff.c

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6204,64 +6204,58 @@ EXPORT_SYMBOL_GPL(skb_mpls_dec_ttl);
62046204
*
62056205
* @header_len: size of linear part
62066206
* @data_len: needed length in frags
6207-
* @max_page_order: max page order desired.
6207+
* @order: max page order desired.
62086208
* @errcode: pointer to error code if any
62096209
* @gfp_mask: allocation mask
62106210
*
62116211
* This can be used to allocate a paged skb, given a maximal order for frags.
62126212
*/
62136213
struct sk_buff *alloc_skb_with_frags(unsigned long header_len,
62146214
unsigned long data_len,
6215-
int max_page_order,
6215+
int order,
62166216
int *errcode,
62176217
gfp_t gfp_mask)
62186218
{
6219-
int npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
62206219
unsigned long chunk;
62216220
struct sk_buff *skb;
62226221
struct page *page;
6223-
int i;
6222+
int nr_frags = 0;
62246223

62256224
*errcode = -EMSGSIZE;
6226-
/* Note this test could be relaxed, if we succeed to allocate
6227-
* high order pages...
6228-
*/
6229-
if (npages > MAX_SKB_FRAGS)
6225+
if (unlikely(data_len > MAX_SKB_FRAGS * (PAGE_SIZE << order)))
62306226
return NULL;
62316227

62326228
*errcode = -ENOBUFS;
62336229
skb = alloc_skb(header_len, gfp_mask);
62346230
if (!skb)
62356231
return NULL;
62366232

6237-
skb->truesize += npages << PAGE_SHIFT;
6238-
6239-
for (i = 0; npages > 0; i++) {
6240-
int order = max_page_order;
6241-
6242-
while (order) {
6243-
if (npages >= 1 << order) {
6244-
page = alloc_pages((gfp_mask & ~__GFP_DIRECT_RECLAIM) |
6245-
__GFP_COMP |
6246-
__GFP_NOWARN,
6247-
order);
6248-
if (page)
6249-
goto fill_page;
6250-
/* Do not retry other high order allocations */
6251-
order = 1;
6252-
max_page_order = 0;
6253-
}
6233+
while (data_len) {
6234+
if (nr_frags == MAX_SKB_FRAGS - 1)
6235+
goto failure;
6236+
while (order && PAGE_ALIGN(data_len) < (PAGE_SIZE << order))
62546237
order--;
6238+
6239+
if (order) {
6240+
page = alloc_pages((gfp_mask & ~__GFP_DIRECT_RECLAIM) |
6241+
__GFP_COMP |
6242+
__GFP_NOWARN,
6243+
order);
6244+
if (!page) {
6245+
order--;
6246+
continue;
6247+
}
6248+
} else {
6249+
page = alloc_page(gfp_mask);
6250+
if (!page)
6251+
goto failure;
62556252
}
6256-
page = alloc_page(gfp_mask);
6257-
if (!page)
6258-
goto failure;
6259-
fill_page:
62606253
chunk = min_t(unsigned long, data_len,
62616254
PAGE_SIZE << order);
6262-
skb_fill_page_desc(skb, i, page, 0, chunk);
6255+
skb_fill_page_desc(skb, nr_frags, page, 0, chunk);
6256+
nr_frags++;
6257+
skb->truesize += (PAGE_SIZE << order);
62636258
data_len -= chunk;
6264-
npages -= 1 << order;
62656259
}
62666260
return skb;
62676261

0 commit comments

Comments
 (0)