Netdev List
 help / color / mirror / Atom feed
* [patch net-next 11/15] vlan: remove usage of dev->master in __vlan_find_dev_deep()
From: Jiri Pirko @ 2012-12-29 10:38 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, bhutchings, faisal.latif, shemminger, fbl,
	roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
	jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
	blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
	nhorman, john.r.fastabend, pablo
In-Reply-To: <1356777522-19652-1-git-send-email-jiri@resnulli.us>

Also, since all users call __vlan_find_dev_deep() with rcu_read_lock,
make no possibility to call this with rtnl mutex held only.

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 net/8021q/vlan_core.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 65e06ab..380440b 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -60,21 +60,25 @@ bool vlan_do_receive(struct sk_buff **skbp)
 	return true;
 }
 
-/* Must be invoked with rcu_read_lock or with RTNL. */
-struct net_device *__vlan_find_dev_deep(struct net_device *real_dev,
+/* Must be invoked with rcu_read_lock. */
+struct net_device *__vlan_find_dev_deep(struct net_device *dev,
 					u16 vlan_id)
 {
-	struct vlan_info *vlan_info = rcu_dereference_rtnl(real_dev->vlan_info);
+	struct vlan_info *vlan_info = rcu_dereference(dev->vlan_info);
 
 	if (vlan_info) {
 		return vlan_group_get_device(&vlan_info->grp, vlan_id);
 	} else {
 		/*
-		 * Bonding slaves do not have grp assigned to themselves.
-		 * Grp is assigned to bonding master instead.
+		 * Lower devices of master uppers (bonding, team) do not have
+		 * grp assigned to themselves. Grp is assigned to upper device
+		 * instead.
 		 */
-		if (netif_is_bond_slave(real_dev))
-			return __vlan_find_dev_deep(real_dev->master, vlan_id);
+		struct net_device *upper_dev;
+
+		upper_dev = netdev_master_upper_dev_get_rcu(dev);
+		if (upper_dev)
+			return __vlan_find_dev_deep(upper_dev, vlan_id);
 	}
 
 	return NULL;
-- 
1.8.0

^ permalink raw reply related

* [patch net-next 10/15] qeth: ensure that __vlan_find_dev_deep() is called with rcu_read_lock
From: Jiri Pirko @ 2012-12-29 10:38 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, bhutchings, faisal.latif, shemminger, fbl,
	roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
	jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
	blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
	nhorman, john.r.fastabend, pablo
In-Reply-To: <1356777522-19652-1-git-send-email-jiri@resnulli.us>

Also benefit from rcu_read_lock held and use __in_dev_get_rcu() in ipv4 case.

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 drivers/s390/net/qeth_l3_main.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 6e5eef0..0749efe 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1640,6 +1640,7 @@ static void qeth_l3_add_mc(struct qeth_card *card, struct in_device *in4_dev)
 	}
 }
 
+/* called with rcu_read_lock */
 static void qeth_l3_add_vlan_mc(struct qeth_card *card)
 {
 	struct in_device *in_dev;
@@ -1652,19 +1653,14 @@ static void qeth_l3_add_vlan_mc(struct qeth_card *card)
 	for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) {
 		struct net_device *netdev;
 
-		rcu_read_lock();
 		netdev = __vlan_find_dev_deep(card->dev, vid);
-		rcu_read_unlock();
 		if (netdev == NULL ||
 		    !(netdev->flags & IFF_UP))
 			continue;
-		in_dev = in_dev_get(netdev);
+		in_dev = __in_dev_get_rcu(netdev);
 		if (!in_dev)
 			continue;
-		rcu_read_lock();
 		qeth_l3_add_mc(card, in_dev);
-		rcu_read_unlock();
-		in_dev_put(in_dev);
 	}
 }
 
@@ -1673,14 +1669,14 @@ static void qeth_l3_add_multicast_ipv4(struct qeth_card *card)
 	struct in_device *in4_dev;
 
 	QETH_CARD_TEXT(card, 4, "chkmcv4");
-	in4_dev = in_dev_get(card->dev);
-	if (in4_dev == NULL)
-		return;
 	rcu_read_lock();
+	in4_dev = __in_dev_get_rcu(card->dev);
+	if (in4_dev == NULL)
+		goto unlock;
 	qeth_l3_add_mc(card, in4_dev);
 	qeth_l3_add_vlan_mc(card);
+unlock:
 	rcu_read_unlock();
-	in_dev_put(in4_dev);
 }
 
 #ifdef CONFIG_QETH_IPV6
@@ -1705,6 +1701,7 @@ static void qeth_l3_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
 	}
 }
 
+/* called with rcu_read_lock */
 static void qeth_l3_add_vlan_mc6(struct qeth_card *card)
 {
 	struct inet6_dev *in_dev;
@@ -1741,10 +1738,12 @@ static void qeth_l3_add_multicast_ipv6(struct qeth_card *card)
 	in6_dev = in6_dev_get(card->dev);
 	if (in6_dev == NULL)
 		return;
+	rcu_read_lock();
 	read_lock_bh(&in6_dev->lock);
 	qeth_l3_add_mc6(card, in6_dev);
 	qeth_l3_add_vlan_mc6(card);
 	read_unlock_bh(&in6_dev->lock);
+	rcu_read_unlock();
 	in6_dev_put(in6_dev);
 }
 #endif /* CONFIG_QETH_IPV6 */
@@ -1813,8 +1812,10 @@ static void qeth_l3_free_vlan_addresses6(struct qeth_card *card,
 static void qeth_l3_free_vlan_addresses(struct qeth_card *card,
 			unsigned short vid)
 {
+	rcu_read_lock();
 	qeth_l3_free_vlan_addresses4(card, vid);
 	qeth_l3_free_vlan_addresses6(card, vid);
+	rcu_read_unlock();
 }
 
 static int qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
-- 
1.8.0

^ permalink raw reply related

* [patch net-next 09/15] qlcnic: guard __vlan_find_dev_deep() by rcu_read_lock
From: Jiri Pirko @ 2012-12-29 10:38 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, bhutchings, faisal.latif, shemminger, fbl,
	roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
	jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
	blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
	nhorman, john.r.fastabend, pablo
In-Reply-To: <1356777522-19652-1-git-send-email-jiri@resnulli.us>

rcu_read_lock was missing here

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index d833f59..95b628f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -2867,12 +2867,14 @@ qlcnic_restore_indev_addr(struct net_device *netdev, unsigned long event)
 
 	qlcnic_config_indev_addr(adapter, netdev, event);
 
+	rcu_read_lock();
 	for_each_set_bit(vid, adapter->vlans, VLAN_N_VID) {
 		dev = __vlan_find_dev_deep(netdev, vid);
 		if (!dev)
 			continue;
 		qlcnic_config_indev_addr(adapter, dev, event);
 	}
+	rcu_read_unlock();
 }
 
 static int qlcnic_netdev_event(struct notifier_block *this,
-- 
1.8.0

^ permalink raw reply related

* [patch net-next 08/15] cxgb3: remove usage of dev->master
From: Jiri Pirko @ 2012-12-29 10:38 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, bhutchings, faisal.latif, shemminger, fbl,
	roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
	jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
	blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
	nhorman, john.r.fastabend, pablo
In-Reply-To: <1356777522-19652-1-git-send-email-jiri@resnulli.us>

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
index 942dace..3f1f501 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
@@ -182,14 +182,17 @@ static struct net_device *get_iff_from_mac(struct adapter *adapter,
 		struct net_device *dev = adapter->port[i];
 
 		if (!memcmp(dev->dev_addr, mac, ETH_ALEN)) {
+			rcu_read_lock();
 			if (vlan && vlan != VLAN_VID_MASK) {
-				rcu_read_lock();
 				dev = __vlan_find_dev_deep(dev, vlan);
-				rcu_read_unlock();
 			} else if (netif_is_bond_slave(dev)) {
-				while (dev->master)
-					dev = dev->master;
+				struct net_device *upper_dev;
+
+				while ((upper_dev =
+					netdev_master_upper_dev_get_rcu(dev)))
+					dev = upper_dev;
 			}
+			rcu_read_unlock();
 			return dev;
 		}
 	}
-- 
1.8.0

^ permalink raw reply related

* [patch net-next 07/15] netpoll: remove usage of dev->master
From: Jiri Pirko @ 2012-12-29 10:38 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, bhutchings, faisal.latif, shemminger, fbl,
	roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
	jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
	blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
	nhorman, john.r.fastabend, pablo
In-Reply-To: <1356777522-19652-1-git-send-email-jiri@resnulli.us>

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 net/core/netpoll.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 3151acf..d2bda8e 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -210,9 +210,12 @@ static void netpoll_poll_dev(struct net_device *dev)
 
 	if (dev->flags & IFF_SLAVE) {
 		if (ni) {
-			struct net_device *bond_dev = dev->master;
+			struct net_device *bond_dev;
 			struct sk_buff *skb;
-			struct netpoll_info *bond_ni = rcu_dereference_bh(bond_dev->npinfo);
+			struct netpoll_info *bond_ni;
+
+			bond_dev = netdev_master_upper_dev_get_rcu(dev);
+			bond_ni = rcu_dereference_bh(bond_dev->npinfo);
 			while ((skb = skb_dequeue(&ni->arp_tx))) {
 				skb->dev = bond_dev;
 				skb_queue_tail(&bond_ni->arp_tx, skb);
@@ -815,7 +818,7 @@ int netpoll_setup(struct netpoll *np)
 		return -ENODEV;
 	}
 
-	if (ndev->master) {
+	if (netdev_master_upper_dev_get(ndev)) {
 		np_err(np, "%s is a slave device, aborting\n", np->dev_name);
 		err = -EBUSY;
 		goto put;
-- 
1.8.0

^ permalink raw reply related

* [patch net-next 06/15] bridge: remove usage of netdev_set_master()
From: Jiri Pirko @ 2012-12-29 10:38 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, bhutchings, faisal.latif, shemminger, fbl,
	roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
	jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
	blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
	nhorman, john.r.fastabend, pablo
In-Reply-To: <1356777522-19652-1-git-send-email-jiri@resnulli.us>

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 net/bridge/br_if.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 37fe693..742e467 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -148,7 +148,7 @@ static void del_nbp(struct net_bridge_port *p)
 	netdev_rx_handler_unregister(dev);
 	synchronize_net();
 
-	netdev_set_master(dev, NULL);
+	netdev_upper_dev_unlink(dev, br->dev);
 
 	br_multicast_del_port(p);
 
@@ -364,7 +364,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 	if (br_netpoll_info(br) && ((err = br_netpoll_enable(p, GFP_KERNEL))))
 		goto err3;
 
-	err = netdev_set_master(dev, br->dev);
+	err = netdev_master_upper_dev_link(dev, br->dev);
 	if (err)
 		goto err4;
 
@@ -403,7 +403,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 	return 0;
 
 err5:
-	netdev_set_master(dev, NULL);
+	netdev_upper_dev_unlink(dev, br->dev);
 err4:
 	br_netpoll_disable(p);
 err3:
-- 
1.8.0

^ permalink raw reply related

* [patch net-next 05/15] team: remove usage of netdev_set_master()
From: Jiri Pirko @ 2012-12-29 10:38 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, bhutchings, faisal.latif, shemminger, fbl,
	roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
	jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
	blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
	nhorman, john.r.fastabend, pablo
In-Reply-To: <1356777522-19652-1-git-send-email-jiri@resnulli.us>

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 drivers/net/team/team.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index ad86660..c19c74e 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1054,10 +1054,11 @@ static int team_port_add(struct team *team, struct net_device *port_dev)
 		}
 	}
 
-	err = netdev_set_master(port_dev, dev);
+	err = netdev_master_upper_dev_link(port_dev, dev);
 	if (err) {
-		netdev_err(dev, "Device %s failed to set master\n", portname);
-		goto err_set_master;
+		netdev_err(dev, "Device %s failed to set upper link\n",
+			   portname);
+		goto err_set_upper_link;
 	}
 
 	err = netdev_rx_handler_register(port_dev, team_handle_frame,
@@ -1090,9 +1091,9 @@ err_option_port_add:
 	netdev_rx_handler_unregister(port_dev);
 
 err_handler_register:
-	netdev_set_master(port_dev, NULL);
+	netdev_upper_dev_unlink(port_dev, dev);
 
-err_set_master:
+err_set_upper_link:
 	team_port_disable_netpoll(port);
 
 err_enable_netpoll:
@@ -1136,7 +1137,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev)
 	team_port_disable(team, port);
 	list_del_rcu(&port->list);
 	netdev_rx_handler_unregister(port_dev);
-	netdev_set_master(port_dev, NULL);
+	netdev_upper_dev_unlink(port_dev, dev);
 	team_port_disable_netpoll(port);
 	vlan_vids_del_by_dev(port_dev, dev);
 	dev_close(port_dev);
-- 
1.8.0

^ permalink raw reply related

* [patch net-next 04/15] rtnetlink: remove usage of dev->master
From: Jiri Pirko @ 2012-12-29 10:38 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, bhutchings, faisal.latif, shemminger, fbl,
	roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
	jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
	blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
	nhorman, john.r.fastabend, pablo
In-Reply-To: <1356777522-19652-1-git-send-email-jiri@resnulli.us>

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 net/core/rtnetlink.c | 69 ++++++++++++++++++++++++++++------------------------
 1 file changed, 37 insertions(+), 32 deletions(-)

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 2ef7a56..ae612f4 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -880,6 +880,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 	const struct rtnl_link_stats64 *stats;
 	struct nlattr *attr, *af_spec;
 	struct rtnl_af_ops *af_ops;
+	struct net_device *upper_dev = netdev_master_upper_dev_get(dev);
 
 	ASSERT_RTNL();
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
@@ -908,8 +909,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 #endif
 	    (dev->ifindex != dev->iflink &&
 	     nla_put_u32(skb, IFLA_LINK, dev->iflink)) ||
-	    (dev->master &&
-	     nla_put_u32(skb, IFLA_MASTER, dev->master->ifindex)) ||
+	    (upper_dev &&
+	     nla_put_u32(skb, IFLA_MASTER, upper_dev->ifindex)) ||
 	    nla_put_u8(skb, IFLA_CARRIER, netif_carrier_ok(dev)) ||
 	    (dev->qdisc &&
 	     nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) ||
@@ -1273,16 +1274,16 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr *attr)
 
 static int do_set_master(struct net_device *dev, int ifindex)
 {
-	struct net_device *master_dev;
+	struct net_device *upper_dev = netdev_master_upper_dev_get(dev);
 	const struct net_device_ops *ops;
 	int err;
 
-	if (dev->master) {
-		if (dev->master->ifindex == ifindex)
+	if (upper_dev) {
+		if (upper_dev->ifindex == ifindex)
 			return 0;
-		ops = dev->master->netdev_ops;
+		ops = upper_dev->netdev_ops;
 		if (ops->ndo_del_slave) {
-			err = ops->ndo_del_slave(dev->master, dev);
+			err = ops->ndo_del_slave(upper_dev, dev);
 			if (err)
 				return err;
 		} else {
@@ -1291,12 +1292,12 @@ static int do_set_master(struct net_device *dev, int ifindex)
 	}
 
 	if (ifindex) {
-		master_dev = __dev_get_by_index(dev_net(dev), ifindex);
-		if (!master_dev)
+		upper_dev = __dev_get_by_index(dev_net(dev), ifindex);
+		if (!upper_dev)
 			return -EINVAL;
-		ops = master_dev->netdev_ops;
+		ops = upper_dev->netdev_ops;
 		if (ops->ndo_add_slave) {
-			err = ops->ndo_add_slave(master_dev, dev);
+			err = ops->ndo_add_slave(upper_dev, dev);
 			if (err)
 				return err;
 		} else {
@@ -2064,7 +2065,6 @@ errout:
 static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
 	struct net *net = sock_net(skb->sk);
-	struct net_device *master = NULL;
 	struct ndmsg *ndm;
 	struct nlattr *tb[NDA_MAX+1];
 	struct net_device *dev;
@@ -2106,10 +2106,10 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 	/* Support fdb on master device the net/bridge default case */
 	if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) &&
 	    (dev->priv_flags & IFF_BRIDGE_PORT)) {
-		master = dev->master;
-		err = master->netdev_ops->ndo_fdb_add(ndm, tb,
-						      dev, addr,
-						      nlh->nlmsg_flags);
+		struct net_device *br_dev = netdev_master_upper_dev_get(dev);
+		const struct net_device_ops *ops = br_dev->netdev_ops;
+
+		err = ops->ndo_fdb_add(ndm, tb, dev, addr, nlh->nlmsg_flags);
 		if (err)
 			goto out;
 		else
@@ -2170,10 +2170,11 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 	/* Support fdb on master device the net/bridge default case */
 	if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) &&
 	    (dev->priv_flags & IFF_BRIDGE_PORT)) {
-		struct net_device *master = dev->master;
+		struct net_device *br_dev = netdev_master_upper_dev_get(dev);
+		const struct net_device_ops *ops = br_dev->netdev_ops;
 
-		if (master->netdev_ops->ndo_fdb_del)
-			err = master->netdev_ops->ndo_fdb_del(ndm, dev, addr);
+		if (ops->ndo_fdb_del)
+			err = ops->ndo_fdb_del(ndm, dev, addr);
 
 		if (err)
 			goto out;
@@ -2257,9 +2258,11 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
 	rcu_read_lock();
 	for_each_netdev_rcu(net, dev) {
 		if (dev->priv_flags & IFF_BRIDGE_PORT) {
-			struct net_device *master = dev->master;
-			const struct net_device_ops *ops = master->netdev_ops;
+			struct net_device *br_dev;
+			const struct net_device_ops *ops;
 
+			br_dev = netdev_master_upper_dev_get(dev);
+			ops = br_dev->netdev_ops;
 			if (ops->ndo_fdb_dump)
 				idx = ops->ndo_fdb_dump(skb, cb, dev, idx);
 		}
@@ -2280,6 +2283,7 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
 	struct ifinfomsg *ifm;
 	struct nlattr *br_afspec;
 	u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
+	struct net_device *br_dev = netdev_master_upper_dev_get(dev);
 
 	nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*ifm), NLM_F_MULTI);
 	if (nlh == NULL)
@@ -2297,8 +2301,8 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
 	if (nla_put_string(skb, IFLA_IFNAME, dev->name) ||
 	    nla_put_u32(skb, IFLA_MTU, dev->mtu) ||
 	    nla_put_u8(skb, IFLA_OPERSTATE, operstate) ||
-	    (dev->master &&
-	     nla_put_u32(skb, IFLA_MASTER, dev->master->ifindex)) ||
+	    (br_dev &&
+	     nla_put_u32(skb, IFLA_MASTER, br_dev->ifindex)) ||
 	    (dev->addr_len &&
 	     nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
 	    (dev->ifindex != dev->iflink &&
@@ -2334,11 +2338,11 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
 	rcu_read_lock();
 	for_each_netdev_rcu(net, dev) {
 		const struct net_device_ops *ops = dev->netdev_ops;
-		struct net_device *master = dev->master;
+		struct net_device *br_dev = netdev_master_upper_dev_get(dev);
 
-		if (master && master->netdev_ops->ndo_bridge_getlink) {
+		if (br_dev && br_dev->netdev_ops->ndo_bridge_getlink) {
 			if (idx >= cb->args[0] &&
-			    master->netdev_ops->ndo_bridge_getlink(
+			    br_dev->netdev_ops->ndo_bridge_getlink(
 				    skb, portid, seq, dev) < 0)
 				break;
 			idx++;
@@ -2375,7 +2379,7 @@ static inline size_t bridge_nlmsg_size(void)
 static int rtnl_bridge_notify(struct net_device *dev, u16 flags)
 {
 	struct net *net = dev_net(dev);
-	struct net_device *master = dev->master;
+	struct net_device *br_dev = netdev_master_upper_dev_get(dev);
 	struct sk_buff *skb;
 	int err = -EOPNOTSUPP;
 
@@ -2386,8 +2390,8 @@ static int rtnl_bridge_notify(struct net_device *dev, u16 flags)
 	}
 
 	if ((!flags || (flags & BRIDGE_FLAGS_MASTER)) &&
-	    master && master->netdev_ops->ndo_bridge_getlink) {
-		err = master->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev);
+	    br_dev && br_dev->netdev_ops->ndo_bridge_getlink) {
+		err = br_dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev);
 		if (err < 0)
 			goto errout;
 	}
@@ -2446,13 +2450,14 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
 	oflags = flags;
 
 	if (!flags || (flags & BRIDGE_FLAGS_MASTER)) {
-		if (!dev->master ||
-		    !dev->master->netdev_ops->ndo_bridge_setlink) {
+		struct net_device *br_dev = netdev_master_upper_dev_get(dev);
+
+		if (!br_dev || !br_dev->netdev_ops->ndo_bridge_setlink) {
 			err = -EOPNOTSUPP;
 			goto out;
 		}
 
-		err = dev->master->netdev_ops->ndo_bridge_setlink(dev, nlh);
+		err = br_dev->netdev_ops->ndo_bridge_setlink(dev, nlh);
 		if (err)
 			goto out;
 
-- 
1.8.0

^ permalink raw reply related

* [patch net-next 03/15] vlan: add link to upper device
From: Jiri Pirko @ 2012-12-29 10:38 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, bhutchings, faisal.latif, shemminger, fbl,
	roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
	jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
	blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
	nhorman, john.r.fastabend, pablo
In-Reply-To: <1356777522-19652-1-git-send-email-jiri@resnulli.us>

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 net/8021q/vlan.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index a292e80..babfde9 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -105,6 +105,8 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
 	 */
 	unregister_netdevice_queue(dev, head);
 
+	netdev_upper_dev_unlink(real_dev, dev);
+
 	if (grp->nr_vlan_devs == 0)
 		vlan_gvrp_uninit_applicant(real_dev);
 
@@ -162,9 +164,13 @@ int register_vlan_dev(struct net_device *dev)
 	if (err < 0)
 		goto out_uninit_applicant;
 
+	err = netdev_upper_dev_link(real_dev, dev);
+	if (err)
+		goto out_uninit_applicant;
+
 	err = register_netdevice(dev);
 	if (err < 0)
-		goto out_uninit_applicant;
+		goto out_upper_dev_unlink;
 
 	/* Account for reference in struct vlan_dev_priv */
 	dev_hold(real_dev);
@@ -180,6 +186,8 @@ int register_vlan_dev(struct net_device *dev)
 
 	return 0;
 
+out_upper_dev_unlink:
+	netdev_upper_dev_unlink(real_dev, dev);
 out_uninit_applicant:
 	if (grp->nr_vlan_devs == 0)
 		vlan_gvrp_uninit_applicant(real_dev);
-- 
1.8.0

^ permalink raw reply related

* [patch net-next 02/15] macvlan: add link to upper device
From: Jiri Pirko @ 2012-12-29 10:38 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, bhutchings, faisal.latif, shemminger, fbl,
	roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
	jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
	blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
	nhorman, john.r.fastabend, pablo
In-Reply-To: <1356777522-19652-1-git-send-email-jiri@resnulli.us>

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 drivers/net/macvlan.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 68a43fe..b7b614f 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -765,16 +765,22 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
 		memcpy(dev->dev_addr, lowerdev->dev_addr, ETH_ALEN);
 	}
 
+	err = netdev_upper_dev_link(lowerdev, dev);
+	if (err)
+		goto destroy_port;
+
 	port->count += 1;
 	err = register_netdevice(dev);
 	if (err < 0)
-		goto destroy_port;
+		goto upper_dev_unlink;
 
 	list_add_tail(&vlan->list, &port->vlans);
 	netif_stacked_transfer_operstate(lowerdev, dev);
 
 	return 0;
 
+upper_dev_unlink:
+	netdev_upper_dev_unlink(lowerdev, dev);
 destroy_port:
 	port->count -= 1;
 	if (!port->count)
@@ -798,6 +804,7 @@ void macvlan_dellink(struct net_device *dev, struct list_head *head)
 
 	list_del(&vlan->list);
 	unregister_netdevice_queue(dev, head);
+	netdev_upper_dev_unlink(vlan->lowerdev, dev);
 }
 EXPORT_SYMBOL_GPL(macvlan_dellink);
 
-- 
1.8.0

^ permalink raw reply related

* [patch net-next 01/15] net: introduce upper device lists
From: Jiri Pirko @ 2012-12-29 10:38 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, bhutchings, faisal.latif, shemminger, fbl,
	roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
	jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
	blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
	nhorman, john.r.fastabend, pablo
In-Reply-To: <1356777522-19652-1-git-send-email-jiri@resnulli.us>

This lists are supposed to serve for storing pointers to all upper devices.
Eventually it will replace dev->master pointer which is used for
bonding, bridge, team but it cannot be used for vlan, macvlan where
there might be multiple upper present. In case the upper link is
replacement for dev->master, it is marked with "master" flag.

New upper device list resolves this limitation. Also, the information
stored in lists is used for preventing looping setups like
"bond->somethingelse->samebond"

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 include/linux/netdevice.h |  14 +++
 net/core/dev.c            | 255 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 265 insertions(+), 4 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 0e1b92a..2e5a217 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1172,6 +1172,8 @@ struct net_device {
 					  * which this device is member of.
 					  */
 
+	struct list_head	upper_dev_list; /* List of upper devices */
+
 	/* Interface address info used in eth_type_trans() */
 	unsigned char		*dev_addr;	/* hw address, (before bcast
 						   because most packets are
@@ -2633,6 +2635,18 @@ extern int		netdev_max_backlog;
 extern int		netdev_tstamp_prequeue;
 extern int		weight_p;
 extern int		bpf_jit_enable;
+
+extern bool netdev_has_upper_dev(struct net_device *dev,
+				 struct net_device *upper_dev);
+extern bool netdev_has_any_upper_dev(struct net_device *dev);
+extern struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
+extern struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev);
+extern int netdev_upper_dev_link(struct net_device *dev,
+				 struct net_device *upper_dev);
+extern int netdev_master_upper_dev_link(struct net_device *dev,
+					struct net_device *upper_dev);
+extern void netdev_upper_dev_unlink(struct net_device *dev,
+				    struct net_device *upper_dev);
 extern int		netdev_set_master(struct net_device *dev, struct net_device *master);
 extern int netdev_set_bond_master(struct net_device *dev,
 				  struct net_device *master);
diff --git a/net/core/dev.c b/net/core/dev.c
index 21c5b97..cf63a85 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4600,6 +4600,248 @@ static int __init dev_proc_init(void)
 #endif	/* CONFIG_PROC_FS */
 
 
+struct netdev_upper {
+	struct net_device *dev;
+	bool master;
+	struct list_head list;
+	struct rcu_head rcu;
+	struct list_head search_list;
+};
+
+static void __append_search_uppers(struct list_head *search_list, struct net_device *dev)
+{
+	struct netdev_upper *upper;
+
+	list_for_each_entry(upper, &dev->upper_dev_list, list) {
+		/* check if this upper is not already in search list */
+		if (list_empty(&upper->search_list))
+			list_add_tail(&upper->search_list, search_list);
+	}
+}
+
+static bool __netdev_has_upper_dev(struct net_device *dev,
+				   struct net_device *upper_dev)
+{
+	LIST_HEAD(search_list);
+	struct netdev_upper *upper;
+	struct netdev_upper *tmp;
+	bool ret = false;
+
+	__append_search_uppers(&search_list, dev);
+	list_for_each_entry(upper, &search_list, search_list) {
+		if (upper->dev == upper_dev) {
+			ret = true;
+			break;
+		}
+		__append_search_uppers(&search_list, upper->dev);
+	}
+	list_for_each_entry_safe(upper, tmp, &search_list, search_list)
+		INIT_LIST_HEAD(&upper->search_list);
+	return ret;
+}
+
+static struct netdev_upper *__netdev_find_upper(struct net_device *dev,
+						struct net_device *upper_dev)
+{
+	struct netdev_upper *upper;
+
+	list_for_each_entry(upper, &dev->upper_dev_list, list) {
+		if (upper->dev == upper_dev)
+			return upper;
+	}
+	return NULL;
+}
+
+/**
+ * netdev_has_upper_dev - Check if device is linked to an upper device
+ * @dev: device
+ * @upper_dev: upper device to check
+ *
+ * Find out if a device is linked to specified upper device and return true
+ * in case it is. The caller must hold the RTNL semaphore.
+ */
+bool netdev_has_upper_dev(struct net_device *dev,
+			  struct net_device *upper_dev)
+{
+	ASSERT_RTNL();
+
+	return __netdev_find_upper(dev, upper_dev);
+}
+EXPORT_SYMBOL(netdev_has_upper_dev);
+
+/**
+ * netdev_has_any_upper_dev - Check if device is linked to some device
+ * @dev: device
+ *
+ * Find out if a device is linked to an upper device and return true in case
+ * it is. The caller must hold the RTNL semaphore.
+ */
+bool netdev_has_any_upper_dev(struct net_device *dev)
+{
+	ASSERT_RTNL();
+
+	return !list_empty(&dev->upper_dev_list);
+}
+EXPORT_SYMBOL(netdev_has_any_upper_dev);
+
+/**
+ * netdev_master_upper_dev_get - Get master upper device
+ * @dev: device
+ *
+ * Find a master upper device and return pointer to it or NULL in case
+ * it's not there. The caller must hold the RTNL semaphore.
+ */
+struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
+{
+	struct netdev_upper *upper;
+
+	ASSERT_RTNL();
+
+	if (list_empty(&dev->upper_dev_list))
+		return NULL;
+
+	upper = list_first_entry(&dev->upper_dev_list,
+				 struct netdev_upper, list);
+	if (likely(upper->master))
+		return upper->dev;
+	return NULL;
+}
+EXPORT_SYMBOL(netdev_master_upper_dev_get);
+
+/**
+ * netdev_master_upper_dev_get_rcu - Get master upper device
+ * @dev: device
+ *
+ * Find a master upper device and return pointer to it or NULL in case
+ * it's not there. The caller must hold the RCU read lock.
+ */
+struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev)
+{
+	struct netdev_upper *upper;
+
+	upper = list_first_or_null_rcu(&dev->upper_dev_list,
+				       struct netdev_upper, list);
+	if (upper && likely(upper->master))
+		return upper->dev;
+	return NULL;
+}
+EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu);
+
+static int __netdev_upper_dev_link(struct net_device *dev,
+				   struct net_device *upper_dev, bool master)
+{
+	struct netdev_upper *upper;
+
+	ASSERT_RTNL();
+
+	if (dev == upper_dev)
+		return -EBUSY;
+	/*
+	 * To prevent loops, check if dev is not upper device to upper_dev.
+	 */
+	if (__netdev_has_upper_dev(upper_dev, dev))
+		return -EBUSY;
+
+	if (__netdev_find_upper(dev, upper_dev))
+		return -EEXIST;
+
+	if (master && netdev_master_upper_dev_get(dev))
+		return -EBUSY;
+
+	upper = kmalloc(sizeof(*upper), GFP_KERNEL);
+	if (!upper)
+		return -ENOMEM;
+
+	upper->dev = upper_dev;
+	upper->master = master;
+	INIT_LIST_HEAD(&upper->search_list);
+
+	/*
+	 * Ensure that master upper link is always the first item in the list.
+	 */
+	if (master)
+		list_add_rcu(&upper->list, &dev->upper_dev_list);
+	else
+		list_add_tail_rcu(&upper->list, &dev->upper_dev_list);
+	dev_hold(upper_dev);
+
+	return 0;
+}
+/**
+ * netdev_upper_dev_link - Add a link to the upper device
+ * @dev: device
+ * @upper_dev: new upper device
+ *
+ * Adds a link to device which is upper to this one. The caller must hold
+ * the RTNL semaphore. On a failure a negative errno code is returned.
+ * On success the reference counts are adjusted and the function
+ * returns zero.
+ */
+int netdev_upper_dev_link(struct net_device *dev,
+			  struct net_device *upper_dev)
+{
+	return __netdev_upper_dev_link(dev, upper_dev, false);
+}
+EXPORT_SYMBOL(netdev_upper_dev_link);
+
+/**
+ * netdev_master_upper_dev_link - Add a master link to the upper device
+ * @dev: device
+ * @upper_dev: new upper device
+ *
+ * Adds a link to device which is upper to this one. In this case, only
+ * one master upper device can be linked, although other non-master devices
+ * might be linked as well. The caller must hold the RTNL semaphore.
+ * On a failure a negative errno code is returned. On success the reference
+ * counts are adjusted and the function returns zero.
+ */
+int netdev_master_upper_dev_link(struct net_device *dev,
+				 struct net_device *upper_dev)
+{
+	return __netdev_upper_dev_link(dev, upper_dev, true);
+}
+EXPORT_SYMBOL(netdev_master_upper_dev_link);
+
+/**
+ * netdev_upper_free_rcu - Frees a upper device list item via the RCU pointer
+ * @entry: the entry's RCU field
+ *
+ * This function is designed to be used as a callback to the call_rcu()
+ * function so that the memory allocated to the netdev upper device list item
+ * can be released safely.
+ */
+static void netdev_upper_free_rcu(struct rcu_head *entry)
+{
+	struct netdev_upper *upper;
+
+	upper = container_of(entry, struct netdev_upper, rcu);
+	kfree(upper);
+}
+
+/**
+ * netdev_upper_dev_unlink - Removes a link to upper device
+ * @dev: device
+ * @upper_dev: new upper device
+ *
+ * Removes a link to device which is upper to this one. The caller must hold
+ * the RTNL semaphore.
+ */
+void netdev_upper_dev_unlink(struct net_device *dev,
+			     struct net_device *upper_dev)
+{
+	struct netdev_upper *upper;
+
+	ASSERT_RTNL();
+
+	upper = __netdev_find_upper(dev, upper_dev);
+	if (!upper)
+		return;
+	list_del_rcu(&upper->list);
+	dev_put(upper_dev);
+	call_rcu(&upper->rcu, netdev_upper_free_rcu);
+}
+EXPORT_SYMBOL(netdev_upper_dev_unlink);
+
 /**
  *	netdev_set_master	-	set up master pointer
  *	@slave: slave device
@@ -4613,19 +4855,23 @@ static int __init dev_proc_init(void)
 int netdev_set_master(struct net_device *slave, struct net_device *master)
 {
 	struct net_device *old = slave->master;
+	int err;
 
 	ASSERT_RTNL();
 
 	if (master) {
 		if (old)
 			return -EBUSY;
-		dev_hold(master);
+		err = netdev_master_upper_dev_link(slave, master);
+		if (err)
+			return err;
 	}
 
 	slave->master = master;
 
 	if (old)
-		dev_put(old);
+		netdev_upper_dev_unlink(slave, master);
+
 	return 0;
 }
 EXPORT_SYMBOL(netdev_set_master);
@@ -5501,8 +5747,8 @@ static void rollback_registered_many(struct list_head *head)
 		if (dev->netdev_ops->ndo_uninit)
 			dev->netdev_ops->ndo_uninit(dev);
 
-		/* Notifier chain MUST detach us from master device. */
-		WARN_ON(dev->master);
+		/* Notifier chain MUST detach us all upper devices. */
+		WARN_ON(netdev_has_any_upper_dev(dev));
 
 		/* Remove entries from kobject tree */
 		netdev_unregister_kobject(dev);
@@ -6210,6 +6456,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
 	INIT_LIST_HEAD(&dev->napi_list);
 	INIT_LIST_HEAD(&dev->unreg_list);
 	INIT_LIST_HEAD(&dev->link_watch_list);
+	INIT_LIST_HEAD(&dev->upper_dev_list);
 	dev->priv_flags = IFF_XMIT_DST_RELEASE;
 	setup(dev);
 
-- 
1.8.0

^ permalink raw reply related

* [patch net-next V3 00/15] net: introduce upper device lists and remove dev->master
From: Jiri Pirko @ 2012-12-29 10:38 UTC (permalink / raw)
  To: netdev
  Cc: davem, edumazet, bhutchings, faisal.latif, shemminger, fbl,
	roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
	jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
	blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
	nhorman, john.r.fastabend, pablo

This is a V3 of a repost of my previous patchset:
"[patch net-next v2 00/15] net: introduce upper device lists and remove dev->master" fomr Aug 14

The discussion around
"[net-next] bonding: don't allow the master to become its slave"
forced me to think about upper<->lower device connections.

This patchset adds a possibility to record upper device linkage.
All upper<->lower devices are converted to use this mechanism right after.
That leads to dev->master removal because this info becomes redundant since
"master links" have the same value.

After all changes, there is no longer possible to do things as:
"bond->someotherdevice->samebond"

Also I think that drivers like cxgb3, qlcnic, qeth would benefit by this
in future by being able to get more appropriate info about l3 addresses.

v2->v3:
- removed recursion in __netdev_has_upper_dev()
- refreshed bits to be applicable on current net-next

v1->v2:
- s/unique/master/ better naming + stays closer to the past
- fixed vlan err goto
- original patch 15 (WARN_ON change) is squashed into the first patch

Jiri Pirko (15):
  net: introduce upper device lists
  macvlan: add link to upper device
  vlan: add link to upper device
  rtnetlink: remove usage of dev->master
  team: remove usage of netdev_set_master()
  bridge: remove usage of netdev_set_master()
  netpoll: remove usage of dev->master
  cxgb3: remove usage of dev->master
  qlcnic: guard __vlan_find_dev_deep() by rcu_read_lock
  qeth: ensure that __vlan_find_dev_deep() is called with rcu_read_lock
  vlan: remove usage of dev->master in __vlan_find_dev_deep()
  nes: remove usage of dev->master
  bonding: remove usage of dev->master
  net: remove no longer used netdev_set_bond_master() and
    netdev_set_master()
  net: kill dev->master

 drivers/infiniband/hw/nes/nes.c                    |   8 +-
 drivers/infiniband/hw/nes/nes_cm.c                 |   2 +-
 drivers/net/bonding/bond_3ad.c                     |  30 +--
 drivers/net/bonding/bond_alb.c                     |   6 +-
 drivers/net/bonding/bond_main.c                    |  94 +++++---
 drivers/net/bonding/bonding.h                      |  14 +-
 drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c |  11 +-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c   |   2 +
 drivers/net/macvlan.c                              |   9 +-
 drivers/net/team/team.c                            |  13 +-
 drivers/s390/net/qeth_l3_main.c                    |  21 +-
 include/linux/netdevice.h                          |  22 +-
 net/8021q/vlan.c                                   |  10 +-
 net/8021q/vlan_core.c                              |  18 +-
 net/bridge/br_if.c                                 |   6 +-
 net/core/dev.c                                     | 262 ++++++++++++++++++---
 net/core/netpoll.c                                 |   9 +-
 net/core/rtnetlink.c                               |  70 +++---
 18 files changed, 425 insertions(+), 182 deletions(-)

-- 
1.8.0

^ permalink raw reply

* Re: Panic: dma_map_area overflow 66 bytes on 3.7+
From: Martin Nybo Andersen @ 2012-12-29 10:29 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David S. Miller, Michal Schmidt, linux-kernel, netdev
In-Reply-To: <1356724390.21409.641.camel@edumazet-glaptop>

On Friday 28 December 2012 20:53:10 Eric Dumazet wrote:
> On Fri, 2012-12-28 at 20:05 +0100, Martin Nybo Andersen wrote:
> > Hi list,
> > 
> > Since the release of 3.7 my main computer has been panicking a couple of
> > times on both 3.7.0 and 3.7.1 because of a 'dma_map_area overflow xx bytes'.
> > 
> > Example screen shot:
> > http://www.tweek.dk/panic.jpg
> > 
> > I can reproduce it somewhat easily by visiting http://www.openstreetmap.org/
> > and zoom erratically with the scroll-button on the mouse.
> > 
> > The panic seems to occur on line 229 of arch/x86/kernel/amd_gart_64.c, and
> > reverting commit aee77e4accbeb2c86b1d294cd84fec4a12dde3bd (r8169: use
> > unlimited DMA burst for TX) seems to fix the problem for me (at least I've
> > not been able to make it panic as before (yet)).
> > 
> > 
> > lspci -v:
> > 00:00.0 Host bridge: Advanced Micro Devices [AMD] nee ATI RS480 Host Bridge (rev 01)
> > 00:02.0 PCI bridge: Advanced Micro Devices [AMD] nee ATI RS480 PCI-X Root Port
> > 00:05.0 PCI bridge: Advanced Micro Devices [AMD] nee ATI RS480 PCI Bridge
> > 00:12.0 SATA controller: Advanced Micro Devices [AMD] nee ATI SB600 Non-Raid-5 SATA
> > 00:13.0 USB controller: Advanced Micro Devices [AMD] nee ATI SB600 USB (OHCI0)
> > 00:13.1 USB controller: Advanced Micro Devices [AMD] nee ATI SB600 USB (OHCI1)
> > 00:13.2 USB controller: Advanced Micro Devices [AMD] nee ATI SB600 USB (OHCI2)
> > 00:13.3 USB controller: Advanced Micro Devices [AMD] nee ATI SB600 USB (OHCI3)
> > 00:13.4 USB controller: Advanced Micro Devices [AMD] nee ATI SB600 USB (OHCI4)
> > 00:13.5 USB controller: Advanced Micro Devices [AMD] nee ATI SB600 USB Controller (EHCI)
> > 00:14.0 SMBus: Advanced Micro Devices [AMD] nee ATI SBx00 SMBus Controller (rev 13)
> > 00:14.1 IDE interface: Advanced Micro Devices [AMD] nee ATI SB600 IDE
> > 00:14.2 Audio device: Advanced Micro Devices [AMD] nee ATI SBx00 Azalia (Intel HDA)
> > 00:14.3 ISA bridge: Advanced Micro Devices [AMD] nee ATI SB600 PCI to LPC Bridge
> > 00:14.4 PCI bridge: Advanced Micro Devices [AMD] nee ATI SBx00 PCI to PCI Bridge
> > 00:18.0 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] HyperTransport Technology Configuration
> > 00:18.1 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] Address Map
> > 00:18.2 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] DRAM Controller
> > 00:18.3 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] Miscellaneous Control
> > 01:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller (rev 01)
> > 02:00.0 VGA compatible controller: NVIDIA Corporation G84 [GeForce 8600 GT] (rev a1)
> > 03:07.0 Multimedia controller: Twinhan Technology Co. Ltd Mantis DTV PCI Bridge Controller [Ver 1.0] (rev 01)
> > 
> > 
> > Please tell, if more info is needed.
> 
> Seems you have CONFIG_IOMMU_DEBUG, is it really what you want ?
That is true, I've enabled CONFIG_IOMMU_DEBUG.
If I want it? It seems like I don't... :-)

> It seems a bit strange we panic in this case
> ( panic_on_overflow = 1;)
I don't know much about IOMMUs, but if the alternative is trashed memory then
I'm in for it.

panic_on_overflow is set on lines 26--27 of arch/x86/kernel/pci-dma.c along
with force_iommu if CONFIG_IOMMU_DEBUG is enabled.

> You could try to add iommu=nopanic to your boot command : packet should
> be dropped, instead of panic.
I opt for disabling CONFIG_IOMMU_DEBUG, as it sets force_iommu as well.

If the only consequence of this is stats.tx_dropped being bumped not too
often, that's ok for me.


Thanks for the quick help! :-)


Regards,
Martin Nybo Andersen

^ permalink raw reply

* Slow speed of tcp connections in a network namespace
From: Andrew Vagin @ 2012-12-29  9:24 UTC (permalink / raw)
  To: netdev; +Cc: vvs

[-- Attachment #1: Type: text/plain, Size: 1419 bytes --]

We found a few nodes, where network works slow in containers.

For testing speed of TCP connections we use wget, which downloads iso
images from the internet.

wget in the new netns reports only 1.5 MB/s, but wget in the root netns
reports 33MB/s.

A few facts:
 * Experiments shows that window size for CT traffic does not increases
   up to ~900, however for host traffic window size increases up to ~14000
 * packets are shuffled in the netns sometimes.
 * tso/gro/gso changes on interfaces does not help
 * issue was _NOT_ reproduced if kernel booted with maxcpus=1 or bnx2.disable_msi=1

I reduced steps to reproduce:
* Create a new network namespace "test" and a veth pair.
  # ip netns add test
  # ip link add name veth0 type veth peer name veth1

* Move veth1 into the netns test
  # ip link set veth1 netns test

* Set ip address on veth1 and proper routing rules are added for this ip
  in the root netns.
  # ip link set up dev veth0;  ip link set up dev veth0
  # ip netns exec test ip a add REMOTE dev veth1
  # ip netns exec test ip r a default via veth1
  # ip r a REMOTE/32 via dev veth0

Tcpdump for both cases are attached to this message.
tcpdump.host - wget in the root netns
tcpdump.netns.host - tcpdump for the host device, wget in the new netns
tcpdump.netns.veth - tcpdump for the veth1 device, wget in the new netns

3.8-rc1 is used for experiments.

Do you have any ideas where is a problem?

[-- Attachment #2: tcpdump.host.gz --]
[-- Type: application/x-gzip, Size: 168126 bytes --]

[-- Attachment #3: tcpdump.netns.veth.gz --]
[-- Type: application/x-gzip, Size: 178809 bytes --]

[-- Attachment #4: tcpdump.netns.host.gz --]
[-- Type: application/x-gzip, Size: 178424 bytes --]

^ permalink raw reply

* [PATCHv2 net-next] bridge: respect RFC2863 operational state
From: Stephen Hemminger @ 2012-12-29  4:15 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20121228.152754.707370216340290808.davem@davemloft.net>

The bridge link detection should follow the operational state
of the lower device, rather than the carrier bit. This allows devices
like tunnels that are controlled by userspace control plane to work
with bridge STP link management.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

---
v2 - add more places and fix typo

 net/bridge/br_if.c      |    6 +++---
 net/bridge/br_netlink.c |    5 ++++-
 net/bridge/br_notify.c  |    2 +-
 net/bridge/br_stp_if.c  |    2 +-
 4 files changed, 9 insertions(+), 6 deletions(-)

--- a/net/bridge/br_if.c	2012-12-27 22:30:53.634796003 -0800
+++ b/net/bridge/br_if.c	2012-12-28 19:54:14.198973683 -0800
@@ -66,14 +66,14 @@ void br_port_carrier_check(struct net_br
 	struct net_device *dev = p->dev;
 	struct net_bridge *br = p->br;
 
-	if (netif_running(dev) && netif_carrier_ok(dev))
+	if (netif_running(dev) && netif_oper_up(dev))
 		p->path_cost = port_cost(dev);
 
 	if (!netif_running(br->dev))
 		return;
 
 	spin_lock_bh(&br->lock);
-	if (netif_running(dev) && netif_carrier_ok(dev)) {
+	if (netif_running(dev) && netif_oper_up(dev)) {
 		if (p->state == BR_STATE_DISABLED)
 			br_stp_enable_port(p);
 	} else {
@@ -383,7 +383,7 @@ int br_add_if(struct net_bridge *br, str
 	spin_lock_bh(&br->lock);
 	changed_addr = br_stp_recalculate_bridge_id(br);
 
-	if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) &&
+	if (netif_running(dev) && netif_oper_up(dev) &&
 	    (br->dev->flags & IFF_UP))
 		br_stp_enable_port(p);
 	spin_unlock_bh(&br->lock);
--- a/net/bridge/br_notify.c	2012-12-27 22:30:23.547098173 -0800
+++ b/net/bridge/br_notify.c	2012-12-28 19:47:57.022761664 -0800
@@ -82,7 +82,7 @@ static int br_device_event(struct notifi
 		break;
 
 	case NETDEV_UP:
-		if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP)) {
+		if (netif_running(br->dev) && netif_oper_up(dev)) {
 			spin_lock_bh(&br->lock);
 			br_stp_enable_port(p);
 			spin_unlock_bh(&br->lock);
--- a/net/bridge/br_netlink.c	2012-12-27 11:36:34.813072288 -0800
+++ b/net/bridge/br_netlink.c	2012-12-28 19:52:24.180078602 -0800
@@ -181,8 +181,11 @@ static int br_set_port_state(struct net_
 	if (p->br->stp_enabled == BR_KERNEL_STP)
 		return -EBUSY;
 
+	/* if device is not up, change is not allowed
+	 * if link is not present, only allowable state is disabled
+	 */
 	if (!netif_running(p->dev) ||
-	    (!netif_carrier_ok(p->dev) && state != BR_STATE_DISABLED))
+	    (!netif_oper_up(p->dev) && state != BR_STATE_DISABLED))
 		return -ENETDOWN;
 
 	p->state = state;
--- a/net/bridge/br_stp_if.c	2012-10-29 09:07:36.618530493 -0700
+++ b/net/bridge/br_stp_if.c	2012-12-28 19:53:37.207345191 -0800
@@ -54,7 +54,7 @@ void br_stp_enable_bridge(struct net_bri
 	br_config_bpdu_generation(br);
 
 	list_for_each_entry(p, &br->port_list, list) {
-		if ((p->dev->flags & IFF_UP) && netif_carrier_ok(p->dev))
+		if (netif_running(p->dev) && netif_oper_up(p->dev))
 			br_stp_enable_port(p);
 
 	}

^ permalink raw reply

* Re: [PATCH] skbuff: make __kmalloc_reserve static
From: David Miller @ 2012-12-29  4:33 UTC (permalink / raw)
  To: shemminger; +Cc: edumazet, netdev
In-Reply-To: <20121228202428.5aa18a7b@nehalam.linuxnetplumber.net>

From: Stephen Hemminger <shemminger@vyatta.com>
Date: Fri, 28 Dec 2012 20:24:28 -0800

> Sparse detected case where this local function should be static.
> It may even allow some compiler optimizations.
> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

Applied.

^ permalink raw reply

* Re: [PATCH] tcp: make proc_tcp_fastopen_key static
From: David Miller @ 2012-12-29  4:33 UTC (permalink / raw)
  To: shemminger; +Cc: netdev
In-Reply-To: <20121228202024.2d3dea76@nehalam.linuxnetplumber.net>

From: Stephen Hemminger <shemminger@vyatta.com>
Date: Fri, 28 Dec 2012 20:20:24 -0800

> Detected by sparse.
> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

Applied.

^ permalink raw reply

* Re: [PATCH] sctp: make sctp_addr_wq_timeout_handler static
From: David Miller @ 2012-12-29  4:33 UTC (permalink / raw)
  To: shemminger; +Cc: vyasevich, sri, nhorman, linux-sctp, netdev
In-Reply-To: <20121228201855.4275db64@nehalam.linuxnetplumber.net>

From: Stephen Hemminger <shemminger@vyatta.com>
Date: Fri, 28 Dec 2012 20:18:55 -0800

> Fix sparse warning about local function that should be static.
> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

Applied.

^ permalink raw reply

* [PATCH] skbuff: make __kmalloc_reserve static
From: Stephen Hemminger @ 2012-12-29  4:24 UTC (permalink / raw)
  To: David Miller, Eric Dumazet; +Cc: netdev

Sparse detected case where this local function should be static.
It may even allow some compiler optimizations.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>


--- a/net/core/skbuff.c	2012-12-28 19:46:31.967615872 -0800
+++ b/net/core/skbuff.c	2012-12-28 20:00:33.343165940 -0800
@@ -155,8 +155,9 @@ static void skb_under_panic(struct sk_bu
  */
 #define kmalloc_reserve(size, gfp, node, pfmemalloc) \
 	 __kmalloc_reserve(size, gfp, node, _RET_IP_, pfmemalloc)
-void *__kmalloc_reserve(size_t size, gfp_t flags, int node, unsigned long ip,
-			 bool *pfmemalloc)
+
+static void *__kmalloc_reserve(size_t size, gfp_t flags, int node,
+			       unsigned long ip, bool *pfmemalloc)
 {
 	void *obj;
 	bool ret_pfmemalloc = false;

^ permalink raw reply

* [PATCH]  tcp: make proc_tcp_fastopen_key static
From: Stephen Hemminger @ 2012-12-29  4:20 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev

Detected by sparse.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>


--- a/net/ipv4/sysctl_net_ipv4.c	2012-11-30 10:29:10.903478045 -0800
+++ b/net/ipv4/sysctl_net_ipv4.c	2012-12-28 20:05:49.687988892 -0800
@@ -232,8 +232,8 @@ static int ipv4_tcp_mem(ctl_table *ctl,
 	return 0;
 }
 
-int proc_tcp_fastopen_key(ctl_table *ctl, int write, void __user *buffer,
-			  size_t *lenp, loff_t *ppos)
+static int proc_tcp_fastopen_key(ctl_table *ctl, int write, void __user *buffer,
+				 size_t *lenp, loff_t *ppos)
 {
 	ctl_table tbl = { .maxlen = (TCP_FASTOPEN_KEY_LENGTH * 2 + 10) };
 	struct tcp_fastopen_context *ctxt;

^ permalink raw reply

* [PATCH] sctp: make sctp_addr_wq_timeout_handler static
From: Stephen Hemminger @ 2012-12-29  4:18 UTC (permalink / raw)
  To: Vlad Yasevich, Sridhar Samudrala, Neil Horman, David S. Miller
  Cc: linux-sctp, netdev

Fix sparse warning about local function that should be static.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>


--- a/net/sctp/protocol.c	2012-12-27 11:36:34.817072247 -0800
+++ b/net/sctp/protocol.c	2012-12-28 20:02:51.445778974 -0800
@@ -595,7 +595,7 @@ static void sctp_v4_ecn_capable(struct s
 	INET_ECN_xmit(sk);
 }
 
-void sctp_addr_wq_timeout_handler(unsigned long arg)
+static void sctp_addr_wq_timeout_handler(unsigned long arg)
 {
 	struct net *net = (struct net *)arg;
 	struct sctp_sockaddr_entry *addrw, *temp;

^ permalink raw reply

* Re: [RFC PATCH 0/3] Make rfc3686 template work with asynchronous block ciphers
From: Herbert Xu @ 2012-12-29  0:08 UTC (permalink / raw)
  To: David Miller; +Cc: jussi.kivilinna, linux-crypto, steffen.klassert, netdev
In-Reply-To: <20121228.152311.290755667605168896.davem@davemloft.net>

On Fri, Dec 28, 2012 at 03:23:11PM -0800, David Miller wrote:
> From: Herbert Xu <herbert@gondor.apana.org.au>
> Date: Sat, 29 Dec 2012 09:42:49 +1100
> 
> > On Fri, Dec 28, 2012 at 12:04:48PM +0200, Jussi Kivilinna wrote:
> >> I'm not sure how this patchset should be dealt with (should 1st patch go
> >> through different tree than 2nd and 3rd?), so therefore it's RFC.
> >> 
> >> Second patch makes rfc3686 template work with asynchronous block ciphers and
> >> third patch changes aesni-intel to use this template. First patch fixed problem
> >> in xfrm_algo found with help of 2nd and 3rd patches and without 1st patch
> >> 2nd patch breaks aes-ctr with IPSEC.
> > 
> > I think the easiest way is to have these patches go through Dave's
> > tree.
> 
> Better yet, Steffen's IPSEC tree :-)

Of course :)
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Re: [PATCH V2] forcedeth: Fix WARNINGS that result when DMA mapping is not checked
From: David Miller @ 2012-12-28 23:30 UTC (permalink / raw)
  To: Larry.Finger; +Cc: linville, linux-wireless, netdev, linux-kernel
In-Reply-To: <1356665141-4498-1-git-send-email-Larry.Finger@lwfinger.net>

From: Larry Finger <Larry.Finger@lwfinger.net>
Date: Thu, 27 Dec 2012 21:25:41 -0600

> With 3.8-rc1, the first call of pci_map_single() that is not checked
> with a corresponding pci_dma_mapping_error() call results in a warning
> with a splat as follows:
> 
> WARNING: at lib/dma-debug.c:933 check_unmap+0x480/0x950()
> Hardware name: HP Pavilion dv2700 Notebook PC
> forcedeth 0000:00:0a.0: DMA-API: device driver failed to check
>  map error[device address=0x00000000b176e002] [size=90 bytes] [mapped as single]
> 
> Reviewed-by: Eric Dumazet <eric.dumazet@gmail.com>
> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>

Applied, thanks Larry.

^ permalink raw reply

* Re: [PATCH net-next] net: use per task frag allocator in skb_append_datato_frags
From: David Miller @ 2012-12-28 23:29 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev
In-Reply-To: <1356710797.21409.150.camel@edumazet-glaptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Fri, 28 Dec 2012 08:06:37 -0800

> From: Eric Dumazet <edumazet@google.com>
> 
> Use the new per task frag allocator in skb_append_datato_frags(),
> to reduce number of frags and page allocator overhead.
> 
> Tested:
>  ifconfig lo mtu 16436
>  perf record netperf -t UDP_STREAM ; perf report 
> 
> before :
>  Throughput: 32928 Mbit/s
 ...
>  after:
>   Throughput: 47185 Mbit/s
 ...
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>

Very nice, applied, thanks Eric.

^ permalink raw reply

* Re: [PATCH] net: qmi_wwan: add Telekom Speedstick LTE II
From: David Miller @ 2012-12-28 23:28 UTC (permalink / raw)
  To: bjorn; +Cc: netdev, linux-usb, tschaefer
In-Reply-To: <1356712255-9488-1-git-send-email-bjorn@mork.no>

From: Bjørn Mork <bjorn@mork.no>
Date: Fri, 28 Dec 2012 17:30:55 +0100

> also known as Alcatel One Touch L100V LTE
> 
> The driver description files gives these names to the vendor specific
> functions on this modem:
> 
>  Application1: VID_1BBB&PID_011E&MI_00
>  Application2: VID_1BBB&PID_011E&MI_01
>  Modem:        VID_1BBB&PID_011E&MI_03
>  Ethernet:     VID_1BBB&PID_011E&MI_04
> 
> Reported-by: Thomas Schäfer <tschaefer@t-online.de>
> Signed-off-by: Bjørn Mork <bjorn@mork.no>

Applied, thanks.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox