aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTaehee Yoo <ap420073@gmail.com>2019-10-21 14:47:54 -0400
committerDavid S. Miller <davem@davemloft.net>2019-10-24 17:53:48 -0400
commit369f61bee0f584aee09f0736431eb9b330c98571 (patch)
tree0f90b64e3e33bea5107062b9f7c77ff4036c0ab0
parent089bca2caed0d0dea7da235ce1fe245808f5ec02 (diff)
team: fix nested locking lockdep warning
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@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/team/team.c16
-rw-r--r--include/linux/if_team.h1
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)
1615 int err; 1615 int err;
1616 1616
1617 team->dev = dev; 1617 team->dev = dev;
1618 mutex_init(&team->lock);
1619 team_set_no_mode(team); 1618 team_set_no_mode(team);
1620 1619
1621 team->pcpu_stats = netdev_alloc_pcpu_stats(struct team_pcpu_stats); 1620 team->pcpu_stats = netdev_alloc_pcpu_stats(struct team_pcpu_stats);
@@ -1642,6 +1641,9 @@ static int team_init(struct net_device *dev)
1642 goto err_options_register; 1641 goto err_options_register;
1643 netif_carrier_off(dev); 1642 netif_carrier_off(dev);
1644 1643
1644 lockdep_register_key(&team->team_lock_key);
1645 __mutex_init(&team->lock, "team->team_lock_key", &team->team_lock_key);
1646
1645 return 0; 1647 return 0;
1646 1648
1647err_options_register: 1649err_options_register:
@@ -1671,6 +1673,7 @@ static void team_uninit(struct net_device *dev)
1671 team_queue_override_fini(team); 1673 team_queue_override_fini(team);
1672 mutex_unlock(&team->lock); 1674 mutex_unlock(&team->lock);
1673 netdev_change_features(dev); 1675 netdev_change_features(dev);
1676 lockdep_unregister_key(&team->team_lock_key);
1674} 1677}
1675 1678
1676static void team_destructor(struct net_device *dev) 1679static 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)
1974 err = team_port_del(team, port_dev); 1977 err = team_port_del(team, port_dev);
1975 mutex_unlock(&team->lock); 1978 mutex_unlock(&team->lock);
1976 1979
1977 if (!err) 1980 if (err)
1978 netdev_change_features(dev); 1981 return err;
1982
1983 if (netif_is_team_master(port_dev)) {
1984 lockdep_unregister_key(&team->team_lock_key);
1985 lockdep_register_key(&team->team_lock_key);
1986 lockdep_set_class(&team->lock, &team->team_lock_key);
1987 }
1988 netdev_change_features(dev);
1979 1989
1980 return err; 1990 return err;
1981} 1991}
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 {
223 atomic_t count_pending; 223 atomic_t count_pending;
224 struct delayed_work dw; 224 struct delayed_work dw;
225 } mcast_rejoin; 225 } mcast_rejoin;
226 struct lock_class_key team_lock_key;
226 long mode_priv[TEAM_MODE_PRIV_LONGS]; 227 long mode_priv[TEAM_MODE_PRIV_LONGS];
227}; 228};
228 229