Search Linux Wireless

[PATCH net v5 05/10] team: fix nested locking lockdep warning

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



team interface could be nested and it's lock variable could be nested too.
But this lock uses static lockdep key and there is no nested locking
handling code such as mutex_lock_nested() and so on.
so the Lockdep would warn about the circular locking scenario that
couldn't happen.
In order to fix, this patch makes the team module to use dynamic lock key
instead of static key.

Test commands:
    ip link add team0 type team
    ip link add team1 type team
    ip link set team0 master team1
    ip link set team0 nomaster
    ip link set team1 master team0
    ip link set team1 nomaster

Splat that looks like:
[   40.364352] WARNING: possible recursive locking detected
[   40.364964] 5.4.0-rc3+ #96 Not tainted
[   40.365405] --------------------------------------------
[   40.365973] ip/750 is trying to acquire lock:
[   40.366542] ffff888060b34c40 (&team->lock){+.+.}, at: team_set_mac_address+0x151/0x290 [team]
[   40.367689]
	       but task is already holding lock:
[   40.368729] ffff888051201c40 (&team->lock){+.+.}, at: team_del_slave+0x29/0x60 [team]
[   40.370280]
	       other info that might help us debug this:
[   40.371159]  Possible unsafe locking scenario:

[   40.371942]        CPU0
[   40.372338]        ----
[   40.372673]   lock(&team->lock);
[   40.373115]   lock(&team->lock);
[   40.373549]
	       *** DEADLOCK ***

[   40.374432]  May be due to missing lock nesting notation

[   40.375338] 2 locks held by ip/750:
[   40.375851]  #0: ffffffffabcc42b0 (rtnl_mutex){+.+.}, at: rtnetlink_rcv_msg+0x466/0x8a0
[   40.376927]  #1: ffff888051201c40 (&team->lock){+.+.}, at: team_del_slave+0x29/0x60 [team]
[   40.377989]
	       stack backtrace:
[   40.378650] CPU: 0 PID: 750 Comm: ip Not tainted 5.4.0-rc3+ #96
[   40.379368] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[   40.380574] Call Trace:
[   40.381208]  dump_stack+0x7c/0xbb
[   40.381959]  __lock_acquire+0x269d/0x3de0
[   40.382817]  ? register_lock_class+0x14d0/0x14d0
[   40.383784]  ? check_chain_key+0x236/0x5d0
[   40.384518]  lock_acquire+0x164/0x3b0
[   40.385074]  ? team_set_mac_address+0x151/0x290 [team]
[   40.385805]  __mutex_lock+0x14d/0x14c0
[   40.386371]  ? team_set_mac_address+0x151/0x290 [team]
[   40.387038]  ? team_set_mac_address+0x151/0x290 [team]
[   40.387632]  ? mutex_lock_io_nested+0x1380/0x1380
[   40.388245]  ? team_del_slave+0x60/0x60 [team]
[   40.388752]  ? rcu_read_lock_sched_held+0x90/0xc0
[   40.389304]  ? rcu_read_lock_bh_held+0xa0/0xa0
[   40.389819]  ? lock_acquire+0x164/0x3b0
[   40.390285]  ? lockdep_rtnl_is_held+0x16/0x20
[   40.390797]  ? team_port_get_rtnl+0x90/0xe0 [team]
[   40.391353]  ? __module_text_address+0x13/0x140
[   40.391886]  ? team_set_mac_address+0x151/0x290 [team]
[   40.392547]  team_set_mac_address+0x151/0x290 [team]
[   40.393111]  dev_set_mac_address+0x1f0/0x3f0
[ ... ]

Fixes: 3d249d4ca7d0 ("net: introduce ethernet teaming device")
Signed-off-by: Taehee Yoo <ap420073@xxxxxxxxx>
---

v4 -> v5 :
 - qdisc part is merge into second patch
v1 -> v4 :
 - This patch is not changed

 drivers/net/team/team.c | 16 +++++++++++++---
 include/linux/if_team.h |  1 +
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 6cea83b48cad..8156b33ee3e7 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1615,7 +1615,6 @@ static int team_init(struct net_device *dev)
 	int err;
 
 	team->dev = dev;
-	mutex_init(&team->lock);
 	team_set_no_mode(team);
 
 	team->pcpu_stats = netdev_alloc_pcpu_stats(struct team_pcpu_stats);
@@ -1642,6 +1641,9 @@ static int team_init(struct net_device *dev)
 		goto err_options_register;
 	netif_carrier_off(dev);
 
+	lockdep_register_key(&team->team_lock_key);
+	__mutex_init(&team->lock, "team->team_lock_key", &team->team_lock_key);
+
 	return 0;
 
 err_options_register:
@@ -1671,6 +1673,7 @@ static void team_uninit(struct net_device *dev)
 	team_queue_override_fini(team);
 	mutex_unlock(&team->lock);
 	netdev_change_features(dev);
+	lockdep_unregister_key(&team->team_lock_key);
 }
 
 static void team_destructor(struct net_device *dev)
@@ -1974,8 +1977,15 @@ static int team_del_slave(struct net_device *dev, struct net_device *port_dev)
 	err = team_port_del(team, port_dev);
 	mutex_unlock(&team->lock);
 
-	if (!err)
-		netdev_change_features(dev);
+	if (err)
+		return err;
+
+	if (netif_is_team_master(port_dev)) {
+		lockdep_unregister_key(&team->team_lock_key);
+		lockdep_register_key(&team->team_lock_key);
+		lockdep_set_class(&team->lock, &team->team_lock_key);
+	}
+	netdev_change_features(dev);
 
 	return err;
 }
diff --git a/include/linux/if_team.h b/include/linux/if_team.h
index 06faa066496f..ec7e4bd07f82 100644
--- a/include/linux/if_team.h
+++ b/include/linux/if_team.h
@@ -223,6 +223,7 @@ struct team {
 		atomic_t count_pending;
 		struct delayed_work dw;
 	} mcast_rejoin;
+	struct lock_class_key team_lock_key;
 	long mode_priv[TEAM_MODE_PRIV_LONGS];
 };
 
-- 
2.17.1




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux