[ Upstream commit c674ac30c5 ]
Macvlan devices try to avoid stacking, but that's not always
successfull or even desired. As an example, the following
configuration is perefectly legal and valid:
eth0 <--- macvlan0 <---- vlan0.10 <--- macvlan1
However, this configuration produces the following lockdep
trace:
[ 115.620418] ======================================================
[ 115.620477] [ INFO: possible circular locking dependency detected ]
[ 115.620516] 3.15.0-rc1+ #24 Not tainted
[ 115.620540] -------------------------------------------------------
[ 115.620577] ip/1704 is trying to acquire lock:
[ 115.620604] (&vlan_netdev_addr_lock_key/1){+.....}, at: [<ffffffff815df49c>] dev_uc_sync+0x3c/0x80
[ 115.620686]
but task is already holding lock:
[ 115.620723] (&macvlan_netdev_addr_lock_key){+.....}, at: [<ffffffff815da5be>] dev_set_rx_mode+0x1e/0x40
[ 115.620795]
which lock already depends on the new lock.
[ 115.620853]
the existing dependency chain (in reverse order) is:
[ 115.620894]
-> #1 (&macvlan_netdev_addr_lock_key){+.....}:
[ 115.620935] [<ffffffff810d57f2>] lock_acquire+0xa2/0x130
[ 115.620974] [<ffffffff816f62e7>] _raw_spin_lock_nested+0x37/0x50
[ 115.621019] [<ffffffffa07296c3>] vlan_dev_set_rx_mode+0x53/0x110 [8021q]
[ 115.621066] [<ffffffff815da557>] __dev_set_rx_mode+0x57/0xa0
[ 115.621105] [<ffffffff815da5c6>] dev_set_rx_mode+0x26/0x40
[ 115.621143] [<ffffffff815da6be>] __dev_open+0xde/0x140
[ 115.621174] [<ffffffff815da9ad>] __dev_change_flags+0x9d/0x170
[ 115.621174] [<ffffffff815daaa9>] dev_change_flags+0x29/0x60
[ 115.621174] [<ffffffff815e7f11>] do_setlink+0x321/0x9a0
[ 115.621174] [<ffffffff815ea59f>] rtnl_newlink+0x51f/0x730
[ 115.621174] [<ffffffff815e6e75>] rtnetlink_rcv_msg+0x95/0x250
[ 115.621174] [<ffffffff81608b19>] netlink_rcv_skb+0xa9/0xc0
[ 115.621174] [<ffffffff815e6dca>] rtnetlink_rcv+0x2a/0x40
[ 115.621174] [<ffffffff81608150>] netlink_unicast+0xf0/0x1c0
[ 115.621174] [<ffffffff8160851f>] netlink_sendmsg+0x2ff/0x740
[ 115.621174] [<ffffffff815bc9db>] sock_sendmsg+0x8b/0xc0
[ 115.621174] [<ffffffff815bd4b9>] ___sys_sendmsg+0x369/0x380
[ 115.621174] [<ffffffff815bdbb2>] __sys_sendmsg+0x42/0x80
[ 115.621174] [<ffffffff815bdc02>] SyS_sendmsg+0x12/0x20
[ 115.621174] [<ffffffff816ffd69>] system_call_fastpath+0x16/0x1b
[ 115.621174]
-> #0 (&vlan_netdev_addr_lock_key/1){+.....}:
[ 115.621174] [<ffffffff810d4d43>] __lock_acquire+0x1773/0x1a60
[ 115.621174] [<ffffffff810d57f2>] lock_acquire+0xa2/0x130
[ 115.621174] [<ffffffff816f62e7>] _raw_spin_lock_nested+0x37/0x50
[ 115.621174] [<ffffffff815df49c>] dev_uc_sync+0x3c/0x80
[ 115.621174] [<ffffffffa0696d2a>] macvlan_set_mac_lists+0xca/0x110 [macvlan]
[ 115.621174] [<ffffffff815da557>] __dev_set_rx_mode+0x57/0xa0
[ 115.621174] [<ffffffff815da5c6>] dev_set_rx_mode+0x26/0x40
[ 115.621174] [<ffffffff815da6be>] __dev_open+0xde/0x140
[ 115.621174] [<ffffffff815da9ad>] __dev_change_flags+0x9d/0x170
[ 115.621174] [<ffffffff815daaa9>] dev_change_flags+0x29/0x60
[ 115.621174] [<ffffffff815e7f11>] do_setlink+0x321/0x9a0
[ 115.621174] [<ffffffff815ea59f>] rtnl_newlink+0x51f/0x730
[ 115.621174] [<ffffffff815e6e75>] rtnetlink_rcv_msg+0x95/0x250
[ 115.621174] [<ffffffff81608b19>] netlink_rcv_skb+0xa9/0xc0
[ 115.621174] [<ffffffff815e6dca>] rtnetlink_rcv+0x2a/0x40
[ 115.621174] [<ffffffff81608150>] netlink_unicast+0xf0/0x1c0
[ 115.621174] [<ffffffff8160851f>] netlink_sendmsg+0x2ff/0x740
[ 115.621174] [<ffffffff815bc9db>] sock_sendmsg+0x8b/0xc0
[ 115.621174] [<ffffffff815bd4b9>] ___sys_sendmsg+0x369/0x380
[ 115.621174] [<ffffffff815bdbb2>] __sys_sendmsg+0x42/0x80
[ 115.621174] [<ffffffff815bdc02>] SyS_sendmsg+0x12/0x20
[ 115.621174] [<ffffffff816ffd69>] system_call_fastpath+0x16/0x1b
[ 115.621174]
other info that might help us debug this:
[ 115.621174] Possible unsafe locking scenario:
[ 115.621174] CPU0 CPU1
[ 115.621174] ---- ----
[ 115.621174] lock(&macvlan_netdev_addr_lock_key);
[ 115.621174] lock(&vlan_netdev_addr_lock_key/1);
[ 115.621174] lock(&macvlan_netdev_addr_lock_key);
[ 115.621174] lock(&vlan_netdev_addr_lock_key/1);
[ 115.621174]
*** DEADLOCK ***
[ 115.621174] 2 locks held by ip/1704:
[ 115.621174] #0: (rtnl_mutex){+.+.+.}, at: [<ffffffff815e6dbb>] rtnetlink_rcv+0x1b/0x40
[ 115.621174] #1: (&macvlan_netdev_addr_lock_key){+.....}, at: [<ffffffff815da5be>] dev_set_rx_mode+0x1e/0x40
[ 115.621174]
stack backtrace:
[ 115.621174] CPU: 3 PID: 1704 Comm: ip Not tainted 3.15.0-rc1+ #24
[ 115.621174] Hardware name: Hewlett-Packard HP xw8400 Workstation/0A08h, BIOS 786D5 v02.38 10/25/2010
[ 115.621174] ffffffff82339ae0 ffff880465f79568 ffffffff816ee20c ffffffff82339ae0
[ 115.621174] ffff880465f795a8 ffffffff816e9e1b ffff880465f79600 ffff880465b019c8
[ 115.621174] 0000000000000001 0000000000000002 ffff880465b019c8 ffff880465b01230
[ 115.621174] Call Trace:
[ 115.621174] [<ffffffff816ee20c>] dump_stack+0x4d/0x66
[ 115.621174] [<ffffffff816e9e1b>] print_circular_bug+0x200/0x20e
[ 115.621174] [<ffffffff810d4d43>] __lock_acquire+0x1773/0x1a60
[ 115.621174] [<ffffffff810d3172>] ? trace_hardirqs_on_caller+0xb2/0x1d0
[ 115.621174] [<ffffffff810d57f2>] lock_acquire+0xa2/0x130
[ 115.621174] [<ffffffff815df49c>] ? dev_uc_sync+0x3c/0x80
[ 115.621174] [<ffffffff816f62e7>] _raw_spin_lock_nested+0x37/0x50
[ 115.621174] [<ffffffff815df49c>] ? dev_uc_sync+0x3c/0x80
[ 115.621174] [<ffffffff815df49c>] dev_uc_sync+0x3c/0x80
[ 115.621174] [<ffffffffa0696d2a>] macvlan_set_mac_lists+0xca/0x110 [macvlan]
[ 115.621174] [<ffffffff815da557>] __dev_set_rx_mode+0x57/0xa0
[ 115.621174] [<ffffffff815da5c6>] dev_set_rx_mode+0x26/0x40
[ 115.621174] [<ffffffff815da6be>] __dev_open+0xde/0x140
[ 115.621174] [<ffffffff815da9ad>] __dev_change_flags+0x9d/0x170
[ 115.621174] [<ffffffff815daaa9>] dev_change_flags+0x29/0x60
[ 115.621174] [<ffffffff811e1db1>] ? mem_cgroup_bad_page_check+0x21/0x30
[ 115.621174] [<ffffffff815e7f11>] do_setlink+0x321/0x9a0
[ 115.621174] [<ffffffff810d394c>] ? __lock_acquire+0x37c/0x1a60
[ 115.621174] [<ffffffff815ea59f>] rtnl_newlink+0x51f/0x730
[ 115.621174] [<ffffffff815ea169>] ? rtnl_newlink+0xe9/0x730
[ 115.621174] [<ffffffff815e6e75>] rtnetlink_rcv_msg+0x95/0x250
[ 115.621174] [<ffffffff810d329d>] ? trace_hardirqs_on+0xd/0x10
[ 115.621174] [<ffffffff815e6dbb>] ? rtnetlink_rcv+0x1b/0x40
[ 115.621174] [<ffffffff815e6de0>] ? rtnetlink_rcv+0x40/0x40
[ 115.621174] [<ffffffff81608b19>] netlink_rcv_skb+0xa9/0xc0
[ 115.621174] [<ffffffff815e6dca>] rtnetlink_rcv+0x2a/0x40
[ 115.621174] [<ffffffff81608150>] netlink_unicast+0xf0/0x1c0
[ 115.621174] [<ffffffff8160851f>] netlink_sendmsg+0x2ff/0x740
[ 115.621174] [<ffffffff815bc9db>] sock_sendmsg+0x8b/0xc0
[ 115.621174] [<ffffffff8119d4af>] ? might_fault+0x5f/0xb0
[ 115.621174] [<ffffffff8119d4f8>] ? might_fault+0xa8/0xb0
[ 115.621174] [<ffffffff8119d4af>] ? might_fault+0x5f/0xb0
[ 115.621174] [<ffffffff815cb51e>] ? verify_iovec+0x5e/0xe0
[ 115.621174] [<ffffffff815bd4b9>] ___sys_sendmsg+0x369/0x380
[ 115.621174] [<ffffffff816faa0d>] ? __do_page_fault+0x11d/0x570
[ 115.621174] [<ffffffff810cfe9f>] ? up_read+0x1f/0x40
[ 115.621174] [<ffffffff816fab04>] ? __do_page_fault+0x214/0x570
[ 115.621174] [<ffffffff8120a10b>] ? mntput_no_expire+0x6b/0x1c0
[ 115.621174] [<ffffffff8120a0b7>] ? mntput_no_expire+0x17/0x1c0
[ 115.621174] [<ffffffff8120a284>] ? mntput+0x24/0x40
[ 115.621174] [<ffffffff815bdbb2>] __sys_sendmsg+0x42/0x80
[ 115.621174] [<ffffffff815bdc02>] SyS_sendmsg+0x12/0x20
[ 115.621174] [<ffffffff816ffd69>] system_call_fastpath+0x16/0x1b
Fix this by correctly providing macvlan lockdep class.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
112 lines
2.7 KiB
C
112 lines
2.7 KiB
C
#ifndef _LINUX_IF_MACVLAN_H
|
|
#define _LINUX_IF_MACVLAN_H
|
|
|
|
#include <linux/if_link.h>
|
|
#include <linux/if_vlan.h>
|
|
#include <linux/list.h>
|
|
#include <linux/netdevice.h>
|
|
#include <linux/netlink.h>
|
|
#include <net/netlink.h>
|
|
#include <linux/u64_stats_sync.h>
|
|
|
|
#if IS_ENABLED(CONFIG_MACVTAP)
|
|
struct socket *macvtap_get_socket(struct file *);
|
|
#else
|
|
#include <linux/err.h>
|
|
#include <linux/errno.h>
|
|
struct file;
|
|
struct socket;
|
|
static inline struct socket *macvtap_get_socket(struct file *f)
|
|
{
|
|
return ERR_PTR(-EINVAL);
|
|
}
|
|
#endif /* CONFIG_MACVTAP */
|
|
|
|
struct macvlan_port;
|
|
struct macvtap_queue;
|
|
|
|
/*
|
|
* Maximum times a macvtap device can be opened. This can be used to
|
|
* configure the number of receive queue, e.g. for multiqueue virtio.
|
|
*/
|
|
#define MAX_MACVTAP_QUEUES 16
|
|
|
|
#define MACVLAN_MC_FILTER_BITS 8
|
|
#define MACVLAN_MC_FILTER_SZ (1 << MACVLAN_MC_FILTER_BITS)
|
|
|
|
struct macvlan_dev {
|
|
struct net_device *dev;
|
|
struct list_head list;
|
|
struct hlist_node hlist;
|
|
struct macvlan_port *port;
|
|
struct net_device *lowerdev;
|
|
void *fwd_priv;
|
|
struct vlan_pcpu_stats __percpu *pcpu_stats;
|
|
|
|
DECLARE_BITMAP(mc_filter, MACVLAN_MC_FILTER_SZ);
|
|
|
|
netdev_features_t set_features;
|
|
enum macvlan_mode mode;
|
|
u16 flags;
|
|
/* This array tracks active taps. */
|
|
struct macvtap_queue __rcu *taps[MAX_MACVTAP_QUEUES];
|
|
/* This list tracks all taps (both enabled and disabled) */
|
|
struct list_head queue_list;
|
|
int numvtaps;
|
|
int numqueues;
|
|
netdev_features_t tap_features;
|
|
int minor;
|
|
int nest_level;
|
|
};
|
|
|
|
static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
|
|
unsigned int len, bool success,
|
|
bool multicast)
|
|
{
|
|
if (likely(success)) {
|
|
struct vlan_pcpu_stats *pcpu_stats;
|
|
|
|
pcpu_stats = this_cpu_ptr(vlan->pcpu_stats);
|
|
u64_stats_update_begin(&pcpu_stats->syncp);
|
|
pcpu_stats->rx_packets++;
|
|
pcpu_stats->rx_bytes += len;
|
|
if (multicast)
|
|
pcpu_stats->rx_multicast++;
|
|
u64_stats_update_end(&pcpu_stats->syncp);
|
|
} else {
|
|
this_cpu_inc(vlan->pcpu_stats->rx_errors);
|
|
}
|
|
}
|
|
|
|
extern void macvlan_common_setup(struct net_device *dev);
|
|
|
|
extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
|
|
struct nlattr *tb[], struct nlattr *data[]);
|
|
|
|
extern void macvlan_count_rx(const struct macvlan_dev *vlan,
|
|
unsigned int len, bool success,
|
|
bool multicast);
|
|
|
|
extern void macvlan_dellink(struct net_device *dev, struct list_head *head);
|
|
|
|
extern int macvlan_link_register(struct rtnl_link_ops *ops);
|
|
|
|
#if IS_ENABLED(CONFIG_MACVLAN)
|
|
static inline struct net_device *
|
|
macvlan_dev_real_dev(const struct net_device *dev)
|
|
{
|
|
struct macvlan_dev *macvlan = netdev_priv(dev);
|
|
|
|
return macvlan->lowerdev;
|
|
}
|
|
#else
|
|
static inline struct net_device *
|
|
macvlan_dev_real_dev(const struct net_device *dev)
|
|
{
|
|
BUG();
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
#endif /* _LINUX_IF_MACVLAN_H */
|