summaryrefslogtreecommitdiffstats
path: root/drivers/net/tun.c
diff options
context:
space:
mode:
authorTahsin Erdogan <trdgn@amazon.com>2023-08-09 09:47:52 -0700
committerJakub Kicinski <kuba@kernel.org>2023-08-10 19:33:35 -0700
commit6231e47b6fadf42da2e7a45b8272e80aed53c444 (patch)
tree88e72bf2193a5d6e53630b2fec8119940b7a6276 /drivers/net/tun.c
parent5604ac35cb6ec34ad608008ba851568c385fd3f4 (diff)
downloadlinux-6231e47b6fadf42da2e7a45b8272e80aed53c444.tar.gz
linux-6231e47b6fadf42da2e7a45b8272e80aed53c444.tar.bz2
linux-6231e47b6fadf42da2e7a45b8272e80aed53c444.zip
tun: avoid high-order page allocation for packet header
When gso.hdr_len is zero and a packet is transmitted via write() or writev(), all payload is treated as header which requires a contiguous memory allocation. This allocation request is harder to satisfy, and may even fail if there is enough fragmentation. Note that sendmsg() code path limits the linear copy length, so this change makes write()/writev() and sendmsg() paths more consistent. Signed-off-by: Tahsin Erdogan <trdgn@amazon.com> Acked-by: Jason Wang <jasowang@redhat.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Willem de Bruijn <willemb@google.com> Link: https://lore.kernel.org/r/20230809164753.2247594-1-trdgn@amazon.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r--drivers/net/tun.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a05765448803..d4bd76297a2a 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1523,7 +1523,7 @@ static struct sk_buff *tun_alloc_skb(struct tun_file *tfile,
int err;
/* Under a page? Don't bother with paged skb. */
- if (prepad + len < PAGE_SIZE || !linear)
+ if (prepad + len < PAGE_SIZE)
linear = len;
if (len - linear > MAX_SKB_FRAGS * (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER))
@@ -1840,6 +1840,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
*/
zerocopy = false;
} else {
+ if (!linear)
+ linear = min_t(size_t, good_linear, copylen);
+
skb = tun_alloc_skb(tfile, align, copylen, linear,
noblock);
}