diff options
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r-- | drivers/net/tun.c | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index f042b0373e5..7eab5fcd064 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -352,7 +352,7 @@ static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb) u32 numqueues = 0; rcu_read_lock(); - numqueues = tun->numqueues; + numqueues = ACCESS_ONCE(tun->numqueues); txq = skb_get_rxhash(skb); if (txq) { @@ -841,7 +841,7 @@ static const struct net_device_ops tap_netdev_ops = { #endif }; -static int tun_flow_init(struct tun_struct *tun) +static void tun_flow_init(struct tun_struct *tun) { int i; @@ -852,8 +852,6 @@ static int tun_flow_init(struct tun_struct *tun) setup_timer(&tun->flow_gc_timer, tun_flow_cleanup, (unsigned long)tun); mod_timer(&tun->flow_gc_timer, round_jiffies_up(jiffies + tun->ageing_time)); - - return 0; } static void tun_flow_uninit(struct tun_struct *tun) @@ -1010,8 +1008,10 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, return -EMSGSIZE; num_pages = get_user_pages_fast(base, size, 0, &page[i]); if (num_pages != size) { - for (i = 0; i < num_pages; i++) - put_page(page[i]); + int j; + + for (j = 0; j < num_pages; j++) + put_page(page[i + j]); return -EFAULT; } truesize = size * PAGE_SIZE; @@ -1530,6 +1530,9 @@ static int tun_flags(struct tun_struct *tun) if (tun->flags & TUN_TAP_MQ) flags |= IFF_MULTI_QUEUE; + if (tun->flags & TUN_PERSIST) + flags |= IFF_PERSIST; + return flags; } @@ -1585,6 +1588,10 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) else return -EINVAL; + if (!!(ifr->ifr_flags & IFF_MULTI_QUEUE) != + !!(tun->flags & TUN_TAP_MQ)) + return -EINVAL; + if (tun_not_capable(tun)) return -EPERM; err = security_tun_dev_open(tun->security); @@ -1655,10 +1662,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) goto err_free_dev; tun_net_init(dev); - - err = tun_flow_init(tun); - if (err < 0) - goto err_free_dev; + tun_flow_init(tun); dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | TUN_USER_FEATURES; @@ -2155,6 +2159,8 @@ static int tun_chr_open(struct inode *inode, struct file * file) set_bit(SOCK_EXTERNALLY_ALLOCATED, &tfile->socket.flags); INIT_LIST_HEAD(&tfile->next); + sock_set_flag(&tfile->sk, SOCK_ZEROCOPY); + return 0; } |