Skip to content

Commit

Permalink
tun: use netdev_alloc_frag() in tun_napi_alloc_frags()
Browse files Browse the repository at this point in the history
In order to cook skbs in the same way than Ethernet drivers,
it is probably better to not use GFP_KERNEL, but rather
use the GFP_ATOMIC and PFMEMALLOC mechanisms provided by
netdev_alloc_frag().

This would allow to use tun driver even in memory stress
situations, especially if swap is used over this tun channel.

Fixes: 90e33d4 ("tun: enable napi_gro_frags() for TUN/TAP driver")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Petar Penkov <peterpenkov96@gmail.com>
Cc: Mahesh Bandewar <maheshb@google.com>
Cc: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Eric Dumazet authored and David S. Miller committed Nov 19, 2018
1 parent 05b0e1d commit aa6daac
Showing 1 changed file with 7 additions and 8 deletions.
15 changes: 7 additions & 8 deletions drivers/net/tun.c
Original file line number Diff line number Diff line change
Expand Up @@ -1478,23 +1478,22 @@ static struct sk_buff *tun_napi_alloc_frags(struct tun_file *tfile,
skb->truesize += skb->data_len;

for (i = 1; i < it->nr_segs; i++) {
struct page_frag *pfrag = &current->task_frag;
size_t fragsz = it->iov[i].iov_len;
struct page *page;
void *frag;

if (fragsz == 0 || fragsz > PAGE_SIZE) {
err = -EINVAL;
goto free;
}

if (!skb_page_frag_refill(fragsz, pfrag, GFP_KERNEL)) {
frag = netdev_alloc_frag(fragsz);
if (!frag) {
err = -ENOMEM;
goto free;
}

skb_fill_page_desc(skb, i - 1, pfrag->page,
pfrag->offset, fragsz);
page_ref_inc(pfrag->page);
pfrag->offset += fragsz;
page = virt_to_head_page(frag);
skb_fill_page_desc(skb, i - 1, page,
frag - page_address(page), fragsz);
}

return skb;
Expand Down

0 comments on commit aa6daac

Please sign in to comment.