aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrei Vagin <avagin@gmail.com>2018-08-08 23:07:35 -0400
committerDavid S. Miller <davem@davemloft.net>2018-08-09 17:25:06 -0400
commit4d99f6602cb552fb58db0c3b1d935bb6fa017f24 (patch)
tree01ef2703ee691058407b15164a05c7dea2f7c461
parent4005a7cb4f553a21d60f24ed7a18fbd26c6db9f4 (diff)
net: allow to call netif_reset_xps_queues() under cpus_read_lock
The definition of static_key_slow_inc() has cpus_read_lock in place. In the virtio_net driver, XPS queues are initialized after setting the queue:cpu affinity in virtnet_set_affinity() which is already protected within cpus_read_lock. Lockdep prints a warning when we are trying to acquire cpus_read_lock when it is already held. This patch adds an ability to call __netif_set_xps_queue under cpus_read_lock(). Acked-by: Jason Wang <jasowang@redhat.com> ============================================ WARNING: possible recursive locking detected 4.18.0-rc3-next-20180703+ #1 Not tainted -------------------------------------------- swapper/0/1 is trying to acquire lock: 00000000cf973d46 (cpu_hotplug_lock.rw_sem){++++}, at: static_key_slow_inc+0xe/0x20 but task is already holding lock: 00000000cf973d46 (cpu_hotplug_lock.rw_sem){++++}, at: init_vqs+0x513/0x5a0 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(cpu_hotplug_lock.rw_sem); lock(cpu_hotplug_lock.rw_sem); *** DEADLOCK *** May be due to missing lock nesting notation 3 locks held by swapper/0/1: #0: 00000000244bc7da (&dev->mutex){....}, at: __driver_attach+0x5a/0x110 #1: 00000000cf973d46 (cpu_hotplug_lock.rw_sem){++++}, at: init_vqs+0x513/0x5a0 #2: 000000005cd8463f (xps_map_mutex){+.+.}, at: __netif_set_xps_queue+0x8d/0xc60 v2: move cpus_read_lock() out of __netif_set_xps_queue() Cc: "Nambiar, Amritha" <amritha.nambiar@intel.com> Cc: "Michael S. Tsirkin" <mst@redhat.com> Cc: Jason Wang <jasowang@redhat.com> Fixes: 8af2c06ff4b1 ("net-sysfs: Add interface for Rx queue(s) map per Tx queue") Signed-off-by: Andrei Vagin <avagin@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/virtio_net.c4
-rw-r--r--net/core/dev.c20
-rw-r--r--net/core/net-sysfs.c4
3 files changed, 22 insertions, 6 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 62311dde6e71..39a7f4452587 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1903,9 +1903,11 @@ static void virtnet_set_affinity(struct virtnet_info *vi)
1903 1903
1904 i = 0; 1904 i = 0;
1905 for_each_online_cpu(cpu) { 1905 for_each_online_cpu(cpu) {
1906 const unsigned long *mask = cpumask_bits(cpumask_of(cpu));
1907
1906 virtqueue_set_affinity(vi->rq[i].vq, cpu); 1908 virtqueue_set_affinity(vi->rq[i].vq, cpu);
1907 virtqueue_set_affinity(vi->sq[i].vq, cpu); 1909 virtqueue_set_affinity(vi->sq[i].vq, cpu);
1908 netif_set_xps_queue(vi->dev, cpumask_of(cpu), i); 1910 __netif_set_xps_queue(vi->dev, mask, i, false);
1909 i++; 1911 i++;
1910 } 1912 }
1911 1913
diff --git a/net/core/dev.c b/net/core/dev.c
index f68122f0ab02..325fc5088370 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2176,6 +2176,7 @@ static void netif_reset_xps_queues(struct net_device *dev, u16 offset,
2176 if (!static_key_false(&xps_needed)) 2176 if (!static_key_false(&xps_needed))
2177 return; 2177 return;
2178 2178
2179 cpus_read_lock();
2179 mutex_lock(&xps_map_mutex); 2180 mutex_lock(&xps_map_mutex);
2180 2181
2181 if (static_key_false(&xps_rxqs_needed)) { 2182 if (static_key_false(&xps_rxqs_needed)) {
@@ -2199,10 +2200,11 @@ static void netif_reset_xps_queues(struct net_device *dev, u16 offset,
2199 2200
2200out_no_maps: 2201out_no_maps:
2201 if (static_key_enabled(&xps_rxqs_needed)) 2202 if (static_key_enabled(&xps_rxqs_needed))
2202 static_key_slow_dec(&xps_rxqs_needed); 2203 static_key_slow_dec_cpuslocked(&xps_rxqs_needed);
2203 2204
2204 static_key_slow_dec(&xps_needed); 2205 static_key_slow_dec_cpuslocked(&xps_needed);
2205 mutex_unlock(&xps_map_mutex); 2206 mutex_unlock(&xps_map_mutex);
2207 cpus_read_unlock();
2206} 2208}
2207 2209
2208static void netif_reset_xps_queues_gt(struct net_device *dev, u16 index) 2210static void netif_reset_xps_queues_gt(struct net_device *dev, u16 index)
@@ -2250,6 +2252,7 @@ static struct xps_map *expand_xps_map(struct xps_map *map, int attr_index,
2250 return new_map; 2252 return new_map;
2251} 2253}
2252 2254
2255/* Must be called under cpus_read_lock */
2253int __netif_set_xps_queue(struct net_device *dev, const unsigned long *mask, 2256int __netif_set_xps_queue(struct net_device *dev, const unsigned long *mask,
2254 u16 index, bool is_rxqs_map) 2257 u16 index, bool is_rxqs_map)
2255{ 2258{
@@ -2317,9 +2320,9 @@ int __netif_set_xps_queue(struct net_device *dev, const unsigned long *mask,
2317 if (!new_dev_maps) 2320 if (!new_dev_maps)
2318 goto out_no_new_maps; 2321 goto out_no_new_maps;
2319 2322
2320 static_key_slow_inc(&xps_needed); 2323 static_key_slow_inc_cpuslocked(&xps_needed);
2321 if (is_rxqs_map) 2324 if (is_rxqs_map)
2322 static_key_slow_inc(&xps_rxqs_needed); 2325 static_key_slow_inc_cpuslocked(&xps_rxqs_needed);
2323 2326
2324 for (j = -1; j = netif_attrmask_next(j, possible_mask, nr_ids), 2327 for (j = -1; j = netif_attrmask_next(j, possible_mask, nr_ids),
2325 j < nr_ids;) { 2328 j < nr_ids;) {
@@ -2448,11 +2451,18 @@ error:
2448 kfree(new_dev_maps); 2451 kfree(new_dev_maps);
2449 return -ENOMEM; 2452 return -ENOMEM;
2450} 2453}
2454EXPORT_SYMBOL_GPL(__netif_set_xps_queue);
2451 2455
2452int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask, 2456int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
2453 u16 index) 2457 u16 index)
2454{ 2458{
2455 return __netif_set_xps_queue(dev, cpumask_bits(mask), index, false); 2459 int ret;
2460
2461 cpus_read_lock();
2462 ret = __netif_set_xps_queue(dev, cpumask_bits(mask), index, false);
2463 cpus_read_unlock();
2464
2465 return ret;
2456} 2466}
2457EXPORT_SYMBOL(netif_set_xps_queue); 2467EXPORT_SYMBOL(netif_set_xps_queue);
2458 2468
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 0a95bcf64cdc..bd67c4d0fcfd 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -26,6 +26,7 @@
26#include <linux/pm_runtime.h> 26#include <linux/pm_runtime.h>
27#include <linux/of.h> 27#include <linux/of.h>
28#include <linux/of_net.h> 28#include <linux/of_net.h>
29#include <linux/cpu.h>
29 30
30#include "net-sysfs.h" 31#include "net-sysfs.h"
31 32
@@ -1400,7 +1401,10 @@ static ssize_t xps_rxqs_store(struct netdev_queue *queue, const char *buf,
1400 return err; 1401 return err;
1401 } 1402 }
1402 1403
1404 cpus_read_lock();
1403 err = __netif_set_xps_queue(dev, mask, index, true); 1405 err = __netif_set_xps_queue(dev, mask, index, true);
1406 cpus_read_unlock();
1407
1404 kfree(mask); 1408 kfree(mask);
1405 return err ? : len; 1409 return err ? : len;
1406} 1410}