net: devlink: take RTNL in port_fill() function only if it is not held
Follow-up patch is going to introduce a netdevice notifier event processing which is called with RTNL mutex held. Processing of this will eventually lead to call to port_notity() and port_fill() which currently takes RTNL mutex internally. So as a temporary solution, propagate a bool indicating if the mutex is already held. This will go away in one of the follow-up patches. Signed-off-by: Jiri Pirko <jiri@nvidia.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
45791e0d00
commit
d41c9dbd12
@ -1278,7 +1278,8 @@ out:
|
||||
static int devlink_nl_port_fill(struct sk_buff *msg,
|
||||
struct devlink_port *devlink_port,
|
||||
enum devlink_command cmd, u32 portid, u32 seq,
|
||||
int flags, struct netlink_ext_ack *extack)
|
||||
int flags, struct netlink_ext_ack *extack,
|
||||
bool rtnl_held)
|
||||
{
|
||||
struct devlink *devlink = devlink_port->devlink;
|
||||
void *hdr;
|
||||
@ -1293,7 +1294,8 @@ static int devlink_nl_port_fill(struct sk_buff *msg,
|
||||
goto nla_put_failure;
|
||||
|
||||
/* Hold rtnl lock while accessing port's netdev attributes. */
|
||||
rtnl_lock();
|
||||
if (!rtnl_held)
|
||||
rtnl_lock();
|
||||
spin_lock_bh(&devlink_port->type_lock);
|
||||
if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type))
|
||||
goto nla_put_failure_type_locked;
|
||||
@ -1321,7 +1323,8 @@ static int devlink_nl_port_fill(struct sk_buff *msg,
|
||||
goto nla_put_failure_type_locked;
|
||||
}
|
||||
spin_unlock_bh(&devlink_port->type_lock);
|
||||
rtnl_unlock();
|
||||
if (!rtnl_held)
|
||||
rtnl_unlock();
|
||||
if (devlink_nl_port_attrs_put(msg, devlink_port))
|
||||
goto nla_put_failure;
|
||||
if (devlink_nl_port_function_attrs_put(msg, devlink_port, extack))
|
||||
@ -1336,14 +1339,15 @@ static int devlink_nl_port_fill(struct sk_buff *msg,
|
||||
|
||||
nla_put_failure_type_locked:
|
||||
spin_unlock_bh(&devlink_port->type_lock);
|
||||
rtnl_unlock();
|
||||
if (!rtnl_held)
|
||||
rtnl_unlock();
|
||||
nla_put_failure:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static void devlink_port_notify(struct devlink_port *devlink_port,
|
||||
enum devlink_command cmd)
|
||||
static void __devlink_port_notify(struct devlink_port *devlink_port,
|
||||
enum devlink_command cmd, bool rtnl_held)
|
||||
{
|
||||
struct devlink *devlink = devlink_port->devlink;
|
||||
struct sk_buff *msg;
|
||||
@ -1358,7 +1362,8 @@ static void devlink_port_notify(struct devlink_port *devlink_port,
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
err = devlink_nl_port_fill(msg, devlink_port, cmd, 0, 0, 0, NULL);
|
||||
err = devlink_nl_port_fill(msg, devlink_port, cmd, 0, 0, 0, NULL,
|
||||
rtnl_held);
|
||||
if (err) {
|
||||
nlmsg_free(msg);
|
||||
return;
|
||||
@ -1368,6 +1373,12 @@ static void devlink_port_notify(struct devlink_port *devlink_port,
|
||||
0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static void devlink_port_notify(struct devlink_port *devlink_port,
|
||||
enum devlink_command cmd)
|
||||
{
|
||||
__devlink_port_notify(devlink_port, cmd, false);
|
||||
}
|
||||
|
||||
static void devlink_rate_notify(struct devlink_rate *devlink_rate,
|
||||
enum devlink_command cmd)
|
||||
{
|
||||
@ -1531,7 +1542,7 @@ static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb,
|
||||
|
||||
err = devlink_nl_port_fill(msg, devlink_port, DEVLINK_CMD_PORT_NEW,
|
||||
info->snd_portid, info->snd_seq, 0,
|
||||
info->extack);
|
||||
info->extack, false);
|
||||
if (err) {
|
||||
nlmsg_free(msg);
|
||||
return err;
|
||||
@ -1561,7 +1572,8 @@ static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg,
|
||||
DEVLINK_CMD_NEW,
|
||||
NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq,
|
||||
NLM_F_MULTI, cb->extack);
|
||||
NLM_F_MULTI, cb->extack,
|
||||
false);
|
||||
if (err) {
|
||||
devl_unlock(devlink);
|
||||
devlink_put(devlink);
|
||||
@ -1773,7 +1785,8 @@ static int devlink_port_new_notify(struct devlink *devlink,
|
||||
}
|
||||
|
||||
err = devlink_nl_port_fill(msg, devlink_port, DEVLINK_CMD_NEW,
|
||||
info->snd_portid, info->snd_seq, 0, NULL);
|
||||
info->snd_portid, info->snd_seq, 0, NULL,
|
||||
false);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@ -10033,7 +10046,7 @@ static void devlink_port_type_netdev_checks(struct devlink_port *devlink_port,
|
||||
|
||||
static void __devlink_port_type_set(struct devlink_port *devlink_port,
|
||||
enum devlink_port_type type,
|
||||
void *type_dev)
|
||||
void *type_dev, bool rtnl_held)
|
||||
{
|
||||
struct net_device *netdev = type_dev;
|
||||
|
||||
@ -10060,7 +10073,7 @@ static void __devlink_port_type_set(struct devlink_port *devlink_port,
|
||||
break;
|
||||
}
|
||||
spin_unlock_bh(&devlink_port->type_lock);
|
||||
devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
|
||||
__devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW, rtnl_held);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -10077,7 +10090,8 @@ void devlink_port_type_eth_set(struct devlink_port *devlink_port,
|
||||
"devlink port type for port %d set to Ethernet without a software interface reference, device type not supported by the kernel?\n",
|
||||
devlink_port->index);
|
||||
|
||||
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, netdev);
|
||||
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, netdev,
|
||||
false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
|
||||
|
||||
@ -10090,7 +10104,8 @@ EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
|
||||
void devlink_port_type_ib_set(struct devlink_port *devlink_port,
|
||||
struct ib_device *ibdev)
|
||||
{
|
||||
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_IB, ibdev);
|
||||
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_IB, ibdev,
|
||||
false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
|
||||
|
||||
@ -10101,7 +10116,8 @@ EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
|
||||
*/
|
||||
void devlink_port_type_clear(struct devlink_port *devlink_port)
|
||||
{
|
||||
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL);
|
||||
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL,
|
||||
false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_port_type_clear);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user