Skip to content

Commit

Permalink
Merge branch 'rtnl-pushdown-prep'
Browse files Browse the repository at this point in the history
Florian Westphal says:

====================
rtnetlink: preparation patches for further rtnl lock pushdown/removal

Patches split large rtnl_fill_ifinfo into smaller chunks
to better see which parts

1. require rtnl
2. do not require it at all
3. rely on rtnl locking now but could be converted

Changes since v3:

I dropped the 'ifalias' patch, I have a change to decouple ifalias and
rtnl mutex, I will send it once this series has been merged.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Sep 28, 2017
2 parents 61f26d9 + 4c82a95 commit f46d963
Showing 1 changed file with 84 additions and 38 deletions.
122 changes: 84 additions & 38 deletions net/core/rtnetlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -522,11 +522,15 @@ static size_t rtnl_link_get_af_size(const struct net_device *dev,
static bool rtnl_have_link_slave_info(const struct net_device *dev)
{
struct net_device *master_dev;
bool ret = false;

master_dev = netdev_master_upper_dev_get((struct net_device *) dev);
rcu_read_lock();

master_dev = netdev_master_upper_dev_get_rcu((struct net_device *)dev);
if (master_dev && master_dev->rtnl_link_ops)
return true;
return false;
ret = true;
rcu_read_unlock();
return ret;
}

static int rtnl_link_slave_info_fill(struct sk_buff *skb,
Expand Down Expand Up @@ -1211,6 +1215,36 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb,
return -EMSGSIZE;
}

static noinline_for_stack int rtnl_fill_vf(struct sk_buff *skb,
struct net_device *dev,
u32 ext_filter_mask)
{
struct nlattr *vfinfo;
int i, num_vfs;

if (!dev->dev.parent || ((ext_filter_mask & RTEXT_FILTER_VF) == 0))
return 0;

num_vfs = dev_num_vf(dev->dev.parent);
if (nla_put_u32(skb, IFLA_NUM_VF, num_vfs))
return -EMSGSIZE;

if (!dev->netdev_ops->ndo_get_vf_config)
return 0;

vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST);
if (!vfinfo)
return -EMSGSIZE;

for (i = 0; i < num_vfs; i++) {
if (rtnl_fill_vfinfo(skb, dev, i, vfinfo))
return -EMSGSIZE;
}

nla_nest_end(skb, vfinfo);
return 0;
}

static int rtnl_fill_link_ifmap(struct sk_buff *skb, struct net_device *dev)
{
struct rtnl_link_ifmap map;
Expand Down Expand Up @@ -1307,6 +1341,48 @@ static u32 rtnl_get_event(unsigned long event)
return rtnl_event_type;
}

static int put_master_ifindex(struct sk_buff *skb, struct net_device *dev)
{
const struct net_device *upper_dev;
int ret = 0;

rcu_read_lock();

upper_dev = netdev_master_upper_dev_get_rcu(dev);
if (upper_dev)
ret = nla_put_u32(skb, IFLA_MASTER, upper_dev->ifindex);

rcu_read_unlock();
return ret;
}

static int nla_put_iflink(struct sk_buff *skb, const struct net_device *dev)
{
int ifindex = dev_get_iflink(dev);

if (dev->ifindex == ifindex)
return 0;

return nla_put_u32(skb, IFLA_LINK, ifindex);
}

static int rtnl_fill_link_netnsid(struct sk_buff *skb,
const struct net_device *dev)
{
if (dev->rtnl_link_ops && dev->rtnl_link_ops->get_link_net) {
struct net *link_net = dev->rtnl_link_ops->get_link_net(dev);

if (!net_eq(dev_net(dev), link_net)) {
int id = peernet2id_alloc(dev_net(dev), link_net);

if (nla_put_s32(skb, IFLA_LINK_NETNSID, id))
return -EMSGSIZE;
}
}

return 0;
}

static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
int type, u32 pid, u32 seq, u32 change,
unsigned int flags, u32 ext_filter_mask,
Expand All @@ -1316,7 +1392,6 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
struct nlmsghdr *nlh;
struct nlattr *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);
Expand Down Expand Up @@ -1345,10 +1420,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
#ifdef CONFIG_RPS
nla_put_u32(skb, IFLA_NUM_RX_QUEUES, dev->num_rx_queues) ||
#endif
(dev->ifindex != dev_get_iflink(dev) &&
nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))) ||
(upper_dev &&
nla_put_u32(skb, IFLA_MASTER, upper_dev->ifindex)) ||
nla_put_iflink(skb, dev) ||
put_master_ifindex(skb, dev) ||
nla_put_u8(skb, IFLA_CARRIER, netif_carrier_ok(dev)) ||
(dev->qdisc &&
nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) ||
Expand Down Expand Up @@ -1385,27 +1458,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
if (rtnl_fill_stats(skb, dev))
goto nla_put_failure;

if (dev->dev.parent && (ext_filter_mask & RTEXT_FILTER_VF) &&
nla_put_u32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent)))
if (rtnl_fill_vf(skb, dev, ext_filter_mask))
goto nla_put_failure;

if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent &&
ext_filter_mask & RTEXT_FILTER_VF) {
int i;
struct nlattr *vfinfo;
int num_vfs = dev_num_vf(dev->dev.parent);

vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST);
if (!vfinfo)
goto nla_put_failure;
for (i = 0; i < num_vfs; i++) {
if (rtnl_fill_vfinfo(skb, dev, i, vfinfo))
goto nla_put_failure;
}

nla_nest_end(skb, vfinfo);
}

if (rtnl_port_fill(skb, dev, ext_filter_mask))
goto nla_put_failure;

Expand All @@ -1417,17 +1472,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
goto nla_put_failure;
}

if (dev->rtnl_link_ops &&
dev->rtnl_link_ops->get_link_net) {
struct net *link_net = dev->rtnl_link_ops->get_link_net(dev);

if (!net_eq(dev_net(dev), link_net)) {
int id = peernet2id_alloc(dev_net(dev), link_net);

if (nla_put_s32(skb, IFLA_LINK_NETNSID, id))
goto nla_put_failure;
}
}
if (rtnl_fill_link_netnsid(skb, dev))
goto nla_put_failure;

if (!(af_spec = nla_nest_start(skb, IFLA_AF_SPEC)))
goto nla_put_failure;
Expand Down

0 comments on commit f46d963

Please sign in to comment.