Skip to content

Commit

Permalink
Merge branch 'rtnetlink-reduce-rtnl-pressure'
Browse files Browse the repository at this point in the history
Eric Dumazet says:

====================
rtnetlink: reduce RTNL pressure for dumps

This series restarts the conversion of rtnl dump operations
to RCU protection, instead of requiring RTNL.

In this new attempt (prior one failed in 2011), I chose to
allow a gradual conversion of selected operations.

After this series, "ip -6 addr" and "ip -4 ro" no longer
need to acquire RTNL.

I refrained from changing inet_dump_ifaddr() and inet6_dump_addr()
to avoid merge conflicts because of two fixes in net tree.

I also started the work for "ip link" future conversion.

v2: rtnl_fill_link_ifmap() always emit IFLA_MAP (Jiri Pirko)
    Added "nexthop: allow nexthop_mpath_fill_node()
           to be called without RTNL" to avoid a lockdep splat (Ido Schimmel)
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Feb 26, 2024
2 parents 5f6000a + 0ec4e48 commit 5fc3903
Show file tree
Hide file tree
Showing 32 changed files with 238 additions and 198 deletions.
4 changes: 2 additions & 2 deletions drivers/infiniband/ulp/ipoib/ipoib_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1272,10 +1272,10 @@ static int ipoib_get_iflink(const struct net_device *dev)

/* parent interface */
if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags))
return dev->ifindex;
return READ_ONCE(dev->ifindex);

/* child/vlan interface */
return priv->parent->ifindex;
return READ_ONCE(priv->parent->ifindex);
}

static u32 ipoib_addr_hash(struct ipoib_neigh_hash *htbl, u8 *daddr)
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/can/vxcan.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ static int vxcan_get_iflink(const struct net_device *dev)

rcu_read_lock();
peer = rcu_dereference(priv->peer);
iflink = peer ? peer->ifindex : 0;
iflink = peer ? READ_ONCE(peer->ifindex) : 0;
rcu_read_unlock();

return iflink;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ static int rmnet_vnd_get_iflink(const struct net_device *dev)
{
struct rmnet_priv *priv = netdev_priv(dev);

return priv->real_dev->ifindex;
return READ_ONCE(priv->real_dev->ifindex);
}

static int rmnet_vnd_init(struct net_device *dev)
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ipvlan/ipvlan_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ static int ipvlan_get_iflink(const struct net_device *dev)
{
struct ipvl_dev *ipvlan = netdev_priv(dev);

return ipvlan->phy_dev->ifindex;
return READ_ONCE(ipvlan->phy_dev->ifindex);
}

static const struct net_device_ops ipvlan_netdev_ops = {
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/macsec.c
Original file line number Diff line number Diff line change
Expand Up @@ -3753,7 +3753,7 @@ static void macsec_get_stats64(struct net_device *dev,

static int macsec_get_iflink(const struct net_device *dev)
{
return macsec_priv(dev)->real_dev->ifindex;
return READ_ONCE(macsec_priv(dev)->real_dev->ifindex);
}

static const struct net_device_ops macsec_netdev_ops = {
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/macvlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -1158,7 +1158,7 @@ static int macvlan_dev_get_iflink(const struct net_device *dev)
{
struct macvlan_dev *vlan = netdev_priv(dev);

return vlan->lowerdev->ifindex;
return READ_ONCE(vlan->lowerdev->ifindex);
}

static const struct ethtool_ops macvlan_ethtool_ops = {
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/netkit.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ static int netkit_get_iflink(const struct net_device *dev)
rcu_read_lock();
peer = rcu_dereference(nk->peer);
if (peer)
iflink = peer->ifindex;
iflink = READ_ONCE(peer->ifindex);
rcu_read_unlock();
return iflink;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/veth.c
Original file line number Diff line number Diff line change
Expand Up @@ -1461,7 +1461,7 @@ static int veth_get_iflink(const struct net_device *dev)

rcu_read_lock();
peer = rcu_dereference(priv->peer);
iflink = peer ? peer->ifindex : 0;
iflink = peer ? READ_ONCE(peer->ifindex) : 0;
rcu_read_unlock();

return iflink;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/virtual/virt_wifi.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ static int virt_wifi_net_device_get_iflink(const struct net_device *dev)
{
struct virt_wifi_netdev_priv *priv = netdev_priv(dev);

return priv->lowerdev->ifindex;
return READ_ONCE(priv->lowerdev->ifindex);
}

static const struct net_device_ops virt_wifi_ops = {
Expand Down
6 changes: 4 additions & 2 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -4354,8 +4354,10 @@ static inline bool netif_testing(const struct net_device *dev)
*/
static inline bool netif_oper_up(const struct net_device *dev)
{
return (dev->operstate == IF_OPER_UP ||
dev->operstate == IF_OPER_UNKNOWN /* backward compat */);
unsigned int operstate = READ_ONCE(dev->operstate);

return operstate == IF_OPER_UP ||
operstate == IF_OPER_UNKNOWN /* backward compat */;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions include/linux/netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ struct netlink_callback {
u16 answer_flags;
u32 min_dump_alloc;
unsigned int prev_seq, seq;
int flags;
bool strict_check;
union {
u8 ctx[48];
Expand Down Expand Up @@ -323,6 +324,7 @@ struct netlink_dump_control {
void *data;
struct module *module;
u32 min_dump_alloc;
int flags;
};

int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
Expand Down
1 change: 1 addition & 0 deletions include/net/ip_fib.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ struct fib_dump_filter {
bool filter_set;
bool dump_routes;
bool dump_exceptions;
bool rtnl_held;
unsigned char protocol;
unsigned char rt_type;
unsigned int flags;
Expand Down
2 changes: 1 addition & 1 deletion include/net/nexthop.h
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ static inline
int nexthop_mpath_fill_node(struct sk_buff *skb, struct nexthop *nh,
u8 rt_family)
{
struct nh_group *nhg = rtnl_dereference(nh->nh_grp);
struct nh_group *nhg = rcu_dereference_rtnl(nh->nh_grp);
int i;

for (i = 0; i < nhg->num_nh; i++) {
Expand Down
1 change: 1 addition & 0 deletions include/net/rtnetlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ typedef int (*rtnl_dumpit_func)(struct sk_buff *, struct netlink_callback *);
enum rtnl_link_flags {
RTNL_FLAG_DOIT_UNLOCKED = BIT(0),
RTNL_FLAG_BULK_DEL_SUPPORTED = BIT(1),
RTNL_FLAG_DUMP_UNLOCKED = BIT(2),
};

enum rtnl_kinds {
Expand Down
4 changes: 2 additions & 2 deletions net/8021q/vlan_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -762,9 +762,9 @@ static void vlan_dev_netpoll_cleanup(struct net_device *dev)

static int vlan_dev_get_iflink(const struct net_device *dev)
{
struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
const struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;

return real_dev->ifindex;
return READ_ONCE(real_dev->ifindex);
}

static int vlan_dev_fill_forward_path(struct net_device_path_ctx *ctx,
Expand Down
6 changes: 3 additions & 3 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ int dev_get_iflink(const struct net_device *dev)
if (dev->netdev_ops && dev->netdev_ops->ndo_get_iflink)
return dev->netdev_ops->ndo_get_iflink(dev);

return dev->ifindex;
return READ_ONCE(dev->ifindex);
}
EXPORT_SYMBOL(dev_get_iflink);

Expand Down Expand Up @@ -8632,12 +8632,12 @@ unsigned int dev_get_flags(const struct net_device *dev)
{
unsigned int flags;

flags = (dev->flags & ~(IFF_PROMISC |
flags = (READ_ONCE(dev->flags) & ~(IFF_PROMISC |
IFF_ALLMULTI |
IFF_RUNNING |
IFF_LOWER_UP |
IFF_DORMANT)) |
(dev->gflags & (IFF_PROMISC |
(READ_ONCE(dev->gflags) & (IFF_PROMISC |
IFF_ALLMULTI));

if (netif_running(dev)) {
Expand Down
36 changes: 19 additions & 17 deletions net/core/rtnetlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1455,17 +1455,18 @@ static noinline_for_stack int rtnl_fill_vf(struct sk_buff *skb,
return 0;
}

static int rtnl_fill_link_ifmap(struct sk_buff *skb, struct net_device *dev)
static int rtnl_fill_link_ifmap(struct sk_buff *skb,
const struct net_device *dev)
{
struct rtnl_link_ifmap map;

memset(&map, 0, sizeof(map));
map.mem_start = dev->mem_start;
map.mem_end = dev->mem_end;
map.base_addr = dev->base_addr;
map.irq = dev->irq;
map.dma = dev->dma;
map.port = dev->if_port;
map.mem_start = READ_ONCE(dev->mem_start);
map.mem_end = READ_ONCE(dev->mem_end);
map.base_addr = READ_ONCE(dev->base_addr);
map.irq = READ_ONCE(dev->irq);
map.dma = READ_ONCE(dev->dma);
map.port = READ_ONCE(dev->if_port);

if (nla_put_64bit(skb, IFLA_MAP, sizeof(map), &map, IFLA_PAD))
return -EMSGSIZE;
Expand Down Expand Up @@ -1611,10 +1612,10 @@ static int put_master_ifindex(struct sk_buff *skb, struct net_device *dev)
static int nla_put_iflink(struct sk_buff *skb, const struct net_device *dev,
bool force)
{
int ifindex = dev_get_iflink(dev);
int iflink = dev_get_iflink(dev);

if (force || dev->ifindex != ifindex)
return nla_put_u32(skb, IFLA_LINK, ifindex);
if (force || READ_ONCE(dev->ifindex) != iflink)
return nla_put_u32(skb, IFLA_LINK, iflink);

return 0;
}
Expand Down Expand Up @@ -1698,14 +1699,15 @@ static int rtnl_fill_alt_ifnames(struct sk_buff *skb,
struct netdev_name_node *name_node;
int count = 0;

list_for_each_entry(name_node, &dev->name_node->list, list) {
list_for_each_entry_rcu(name_node, &dev->name_node->list, list) {
if (nla_put_string(skb, IFLA_ALT_IFNAME, name_node->name))
return -EMSGSIZE;
count++;
}
return count;
}

/* RCU protected. */
static int rtnl_fill_prop_list(struct sk_buff *skb,
const struct net_device *dev)
{
Expand Down Expand Up @@ -1875,9 +1877,6 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
goto nla_put_failure;
}

if (rtnl_fill_link_ifmap(skb, dev))
goto nla_put_failure;

if (dev->addr_len) {
if (nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr) ||
nla_put(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast))
Expand Down Expand Up @@ -1927,10 +1926,11 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
rcu_read_lock();
if (rtnl_fill_link_af(skb, dev, ext_filter_mask))
goto nla_put_failure_rcu;
rcu_read_unlock();

if (rtnl_fill_link_ifmap(skb, dev))
goto nla_put_failure_rcu;
if (rtnl_fill_prop_list(skb, dev))
goto nla_put_failure;
goto nla_put_failure_rcu;
rcu_read_unlock();

if (dev->dev.parent &&
nla_put_string(skb, IFLA_PARENT_DEV_NAME,
Expand Down Expand Up @@ -6532,6 +6532,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
}
owner = link->owner;
dumpit = link->dumpit;
flags = link->flags;

if (type == RTM_GETLINK - RTM_BASE)
min_dump_alloc = rtnl_calcit(skb, nlh);
Expand All @@ -6549,6 +6550,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
.dump = dumpit,
.min_dump_alloc = min_dump_alloc,
.module = owner,
.flags = flags,
};
err = netlink_dump_start(rtnl, skb, nlh, &c);
/* netlink_dump_start() will keep a reference on
Expand Down
2 changes: 1 addition & 1 deletion net/dsa/user.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ void dsa_user_mii_bus_init(struct dsa_switch *ds)
/* user device handling ****************************************************/
static int dsa_user_get_iflink(const struct net_device *dev)
{
return dsa_user_to_conduit(dev)->ifindex;
return READ_ONCE(dsa_user_to_conduit(dev)->ifindex);
}

static int dsa_user_open(struct net_device *dev)
Expand Down
2 changes: 1 addition & 1 deletion net/ieee802154/6lowpan/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ static int lowpan_neigh_construct(struct net_device *dev, struct neighbour *n)

static int lowpan_get_iflink(const struct net_device *dev)
{
return lowpan_802154_dev(dev)->wdev->ifindex;
return READ_ONCE(lowpan_802154_dev(dev)->wdev->ifindex);
}

static const struct net_device_ops lowpan_netdev_ops = {
Expand Down
Loading

0 comments on commit 5fc3903

Please sign in to comment.