xen-netback: don't populate the hash cache on XenBus disconnect
authorIgor Druzhinin <igor.druzhinin@citrix.com>
Thu, 28 Feb 2019 14:11:26 +0000 (14:11 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Mar 2019 21:03:09 +0000 (14:03 -0700)
[ Upstream commit a2288d4e355992d369c50c45d017a85f6061ff71 ]

Occasionally, during the disconnection procedure on XenBus which
includes hash cache deinitialization there might be some packets
still in-flight on other processors. Handling of these packets includes
hashing and hash cache population that finally results in hash cache
data structure corruption.

In order to avoid this we prevent hashing of those packets if there
are no queues initialized. In that case RCU protection of queues guards
the hash cache as well.

Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
Reviewed-by: Paul Durrant <paul.durrant@citrix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/xen-netback/hash.c
drivers/net/xen-netback/interface.c

index 3b6fb5b3bdb23ce6ab65b9947ba95cecbd8b59b1..6414cc6b903269630f355ae94bc15c8bac9364f8 100644 (file)
@@ -435,6 +435,8 @@ void xenvif_init_hash(struct xenvif *vif)
        if (xenvif_hash_cache_size == 0)
                return;
 
+       BUG_ON(vif->hash.cache.count);
+
        spin_lock_init(&vif->hash.cache.lock);
        INIT_LIST_HEAD(&vif->hash.cache.list);
 }
index 4491ca5aee906c1b29342bc12c692e175d857505..d465071656b5aa22d0b3ba63d1e8d998f5b3e459 100644 (file)
@@ -153,6 +153,13 @@ static u16 xenvif_select_queue(struct net_device *dev, struct sk_buff *skb,
 {
        struct xenvif *vif = netdev_priv(dev);
        unsigned int size = vif->hash.size;
+       unsigned int num_queues;
+
+       /* If queues are not set up internally - always return 0
+        * as the packet going to be dropped anyway */
+       num_queues = READ_ONCE(vif->num_queues);
+       if (num_queues < 1)
+               return 0;
 
        if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE)
                return fallback(dev, skb) % dev->real_num_tx_queues;