mirror of https://gitee.com/openkylin/linux.git
tun: use netdev_alloc_frag() in tun_napi_alloc_frags()
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: 90e33d4594
("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>
This commit is contained in:
parent
05b0e1d698
commit
aa6daacaa1
|
@ -1478,23 +1478,22 @@ static struct sk_buff *tun_napi_alloc_frags(struct tun_file *tfile,
|
||||||
skb->truesize += skb->data_len;
|
skb->truesize += skb->data_len;
|
||||||
|
|
||||||
for (i = 1; i < it->nr_segs; i++) {
|
for (i = 1; i < it->nr_segs; i++) {
|
||||||
struct page_frag *pfrag = ¤t->task_frag;
|
|
||||||
size_t fragsz = it->iov[i].iov_len;
|
size_t fragsz = it->iov[i].iov_len;
|
||||||
|
struct page *page;
|
||||||
|
void *frag;
|
||||||
|
|
||||||
if (fragsz == 0 || fragsz > PAGE_SIZE) {
|
if (fragsz == 0 || fragsz > PAGE_SIZE) {
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto free;
|
goto free;
|
||||||
}
|
}
|
||||||
|
frag = netdev_alloc_frag(fragsz);
|
||||||
if (!skb_page_frag_refill(fragsz, pfrag, GFP_KERNEL)) {
|
if (!frag) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto free;
|
goto free;
|
||||||
}
|
}
|
||||||
|
page = virt_to_head_page(frag);
|
||||||
skb_fill_page_desc(skb, i - 1, pfrag->page,
|
skb_fill_page_desc(skb, i - 1, page,
|
||||||
pfrag->offset, fragsz);
|
frag - page_address(page), fragsz);
|
||||||
page_ref_inc(pfrag->page);
|
|
||||||
pfrag->offset += fragsz;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return skb;
|
return skb;
|
||||||
|
|
Loading…
Reference in New Issue