|
@@ -628,6 +628,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
|
|
|
const struct iovec *iv, unsigned long total_len,
|
|
|
size_t count, int noblock)
|
|
|
{
|
|
|
+ int good_linear = SKB_MAX_HEAD(NET_IP_ALIGN);
|
|
|
struct sk_buff *skb;
|
|
|
struct macvlan_dev *vlan;
|
|
|
unsigned long len = total_len;
|
|
@@ -670,6 +671,8 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
|
|
|
|
|
|
if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) {
|
|
|
copylen = vnet_hdr.hdr_len ? vnet_hdr.hdr_len : GOODCOPY_LEN;
|
|
|
+ if (copylen > good_linear)
|
|
|
+ copylen = good_linear;
|
|
|
linear = copylen;
|
|
|
if (iov_pages(iv, vnet_hdr_len + copylen, count)
|
|
|
<= MAX_SKB_FRAGS)
|
|
@@ -678,7 +681,10 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
|
|
|
|
|
|
if (!zerocopy) {
|
|
|
copylen = len;
|
|
|
- linear = vnet_hdr.hdr_len;
|
|
|
+ if (vnet_hdr.hdr_len > good_linear)
|
|
|
+ linear = good_linear;
|
|
|
+ else
|
|
|
+ linear = vnet_hdr.hdr_len;
|
|
|
}
|
|
|
|
|
|
skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen,
|