Skip to content

Commit

Permalink
vlan: use dynamic lockdep key instead of subclass
Browse files Browse the repository at this point in the history
All VLAN device has same lockdep key and subclass is initialized with
nest_level.
But actual nest_level value can be changed when a lower device is attached.
And at this moment, the subclass should be updated but it seems to be
unsafe.
So this patch makes VLAN use dynamic lockdep key instead of the subclass.

Test commands:
   ip link add dummy0 type dummy
   ip link set dummy0 up
   ip link add bond0 type bond

   ip link add vlan_dummy1 link dummy0 type vlan id 1
   ip link add vlan_bond1 link bond0 type vlan id 2
   ip link set vlan_dummy1 master bond0

   ip link set bond0 up
   ip link set vlan_dummy1 up
   ip link set vlan_bond1 up

Both vlan_dummy1 and vlan_bond1 have the same subclass and it makes
unnecessary deadlock warning message.

Splat looks like:
[  149.244978] ============================================
[  149.244978] WARNING: possible recursive locking detected
[  149.244978] 5.3.0-rc7+ torvalds#322 Not tainted
[  149.244978] --------------------------------------------
[  149.244978] ip/1340 is trying to acquire lock:
[  149.244978] 000000001399b1a7 (&vlan_netdev_addr_lock_key/1){+...}, at: dev_uc_sync_multiple+0xfa/0x1a0
[  149.279600]
[  149.279600] but task is already holding lock:
[  149.279600] 00000000b963d9b4 (&vlan_netdev_addr_lock_key/1){+...}, at: dev_set_rx_mode+0x19/0x30
[  149.279600]
[  149.279600] other info that might help us debug this:
[  149.305981]  Possible unsafe locking scenario:
[  149.305981]
[  149.305981]        CPU0
[  149.305981]        ----
[  149.305981]   lock(&vlan_netdev_addr_lock_key/1);
[  149.305981]   lock(&vlan_netdev_addr_lock_key/1);
[  149.326258]
[  149.326258]  *** DEADLOCK ***
[  149.326258]
[  149.326258]  May be due to missing lock nesting notation
[  149.326258]
[  149.326258] 4 locks held by ip/1340:
[  149.326258]  #0: 00000000927f0698 (rtnl_mutex){+.+.}, at: rtnetlink_rcv_msg+0x466/0x8a0
[  149.326258]  #1: 00000000b963d9b4 (&vlan_netdev_addr_lock_key/1){+...}, at: dev_set_rx_mode+0x19/0x30
[  149.326258]  #2: 0000000027395445 (&dev_addr_list_lock_key/3){+...}, at: dev_mc_sync+0xfa/0x1a0
[  149.369961]  #3: 00000000ce334932 (rcu_read_lock){....}, at: bond_set_rx_mode+0x5/0x3c0 [bonding]
[  149.369961]
[  149.369961] stack backtrace:
[  149.369961] CPU: 1 PID: 1340 Comm: ip Not tainted 5.3.0-rc7+ torvalds#322
[  149.369961] Call Trace:
[  149.369961]  dump_stack+0x7c/0xbb
[  149.369961]  __lock_acquire+0x26a9/0x3de0
[  149.369961]  ? register_lock_class+0x14d0/0x14d0
[  149.369961]  ? register_lock_class+0x14d0/0x14d0
[  149.369961]  lock_acquire+0x164/0x3b0
[  149.433970]  ? dev_uc_sync_multiple+0xfa/0x1a0
[  149.433970]  _raw_spin_lock_nested+0x2e/0x60
[  149.433970]  ? dev_uc_sync_multiple+0xfa/0x1a0
[  149.433970]  dev_uc_sync_multiple+0xfa/0x1a0
[  149.433970]  bond_set_rx_mode+0x269/0x3c0 [bonding]
[  149.433970]  ? bond_init+0x6f0/0x6f0 [bonding]
[  149.433970]  dev_mc_sync+0x15a/0x1a0
[  149.433970]  vlan_dev_set_rx_mode+0x37/0x80 [8021q]
[  149.433970]  dev_set_rx_mode+0x21/0x30
[  149.433970]  __dev_open+0x202/0x310
[  149.433970]  ? dev_set_rx_mode+0x30/0x30
[  149.433970]  ? mark_held_locks+0xa5/0xe0
[  149.433970]  ? __local_bh_enable_ip+0xe9/0x1b0
[  149.433970]  __dev_change_flags+0x3c3/0x500
[  ... ]

Fixes: 0fe1e56 ("[VLAN]: nested VLAN: fix lockdep's recursive locking warning")
Signed-off-by: Taehee Yoo <[email protected]>
  • Loading branch information
TaeheeYoo authored and intel-lab-lkp committed Sep 6, 2019
1 parent 3dab60d commit e0ed79c
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 13 deletions.
3 changes: 3 additions & 0 deletions include/linux/if_vlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ struct vlan_dev_priv {
struct netpoll *netpoll;
#endif
unsigned int nest_level;

struct lock_class_key xmit_lock_key;
struct lock_class_key addr_lock_key;
};

static inline struct vlan_dev_priv *vlan_dev_priv(const struct net_device *dev)
Expand Down
28 changes: 15 additions & 13 deletions net/8021q/vlan_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -494,24 +494,24 @@ static void vlan_dev_set_rx_mode(struct net_device *vlan_dev)
* "super class" of normal network devices; split their locks off into a
* separate class since they always nest.
*/
static struct lock_class_key vlan_netdev_xmit_lock_key;
static struct lock_class_key vlan_netdev_addr_lock_key;

static void vlan_dev_set_lockdep_one(struct net_device *dev,
struct netdev_queue *txq,
void *_subclass)
void *_unused)
{
lockdep_set_class_and_subclass(&txq->_xmit_lock,
&vlan_netdev_xmit_lock_key,
*(int *)_subclass);
struct vlan_dev_priv *vlan = vlan_dev_priv(dev);

lockdep_set_class(&txq->_xmit_lock, &vlan->xmit_lock_key);
}

static void vlan_dev_set_lockdep_class(struct net_device *dev, int subclass)
static void vlan_dev_set_lockdep_class(struct net_device *dev)
{
lockdep_set_class_and_subclass(&dev->addr_list_lock,
&vlan_netdev_addr_lock_key,
subclass);
netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, &subclass);
struct vlan_dev_priv *vlan = vlan_dev_priv(dev);

lockdep_register_key(&vlan->addr_lock_key);
lockdep_set_class(&dev->addr_list_lock, &vlan->addr_lock_key);

lockdep_register_key(&vlan->xmit_lock_key);
netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, NULL);
}

static int vlan_dev_get_lock_subclass(struct net_device *dev)
Expand Down Expand Up @@ -609,7 +609,7 @@ static int vlan_dev_init(struct net_device *dev)

SET_NETDEV_DEVTYPE(dev, &vlan_type);

vlan_dev_set_lockdep_class(dev, vlan_dev_get_lock_subclass(dev));
vlan_dev_set_lockdep_class(dev);

vlan->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats);
if (!vlan->vlan_pcpu_stats)
Expand All @@ -630,6 +630,8 @@ static void vlan_dev_uninit(struct net_device *dev)
kfree(pm);
}
}
lockdep_unregister_key(&vlan->addr_lock_key);
lockdep_unregister_key(&vlan->xmit_lock_key);
}

static netdev_features_t vlan_dev_fix_features(struct net_device *dev,
Expand Down

0 comments on commit e0ed79c

Please sign in to comment.