summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorIgor Druzhinin <igor.druzhinin@citrix.com>2019-02-28 14:11:26 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-03-13 14:04:53 -0700
commit2e6b3933008c5d48995e89f75974da848f5ec4b4 (patch)
tree29c9360a8ee505b8b5f366f5121a887c974a115f /drivers/net
parent375d6d454a95ebacb9c6eb0b715da05a4458ffef (diff)
xen-netback: don't populate the hash cache on XenBus disconnect
[ 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>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/xen-netback/hash.c2
-rw-r--r--drivers/net/xen-netback/interface.c7
2 files changed, 9 insertions, 0 deletions
diff --git a/drivers/net/xen-netback/hash.c b/drivers/net/xen-netback/hash.c
index 3b6fb5b3bdb2..6414cc6b9032 100644
--- a/drivers/net/xen-netback/hash.c
+++ b/drivers/net/xen-netback/hash.c
@@ -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);
}
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 618013e7f87b..cae691486105 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -152,6 +152,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;