Skip to content

Commit d41c9db

Browse files
Jiri Pirkokuba-moo
authored andcommitted
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 <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 45791e0 commit d41c9db

File tree

1 file changed

+31
-15
lines changed

1 file changed

+31
-15
lines changed

net/core/devlink.c

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,7 +1278,8 @@ devlink_nl_port_function_attrs_put(struct sk_buff *msg, struct devlink_port *por
12781278
static int devlink_nl_port_fill(struct sk_buff *msg,
12791279
struct devlink_port *devlink_port,
12801280
enum devlink_command cmd, u32 portid, u32 seq,
1281-
int flags, struct netlink_ext_ack *extack)
1281+
int flags, struct netlink_ext_ack *extack,
1282+
bool rtnl_held)
12821283
{
12831284
struct devlink *devlink = devlink_port->devlink;
12841285
void *hdr;
@@ -1293,7 +1294,8 @@ static int devlink_nl_port_fill(struct sk_buff *msg,
12931294
goto nla_put_failure;
12941295

12951296
/* Hold rtnl lock while accessing port's netdev attributes. */
1296-
rtnl_lock();
1297+
if (!rtnl_held)
1298+
rtnl_lock();
12971299
spin_lock_bh(&devlink_port->type_lock);
12981300
if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type))
12991301
goto nla_put_failure_type_locked;
@@ -1321,7 +1323,8 @@ static int devlink_nl_port_fill(struct sk_buff *msg,
13211323
goto nla_put_failure_type_locked;
13221324
}
13231325
spin_unlock_bh(&devlink_port->type_lock);
1324-
rtnl_unlock();
1326+
if (!rtnl_held)
1327+
rtnl_unlock();
13251328
if (devlink_nl_port_attrs_put(msg, devlink_port))
13261329
goto nla_put_failure;
13271330
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,
13361339

13371340
nla_put_failure_type_locked:
13381341
spin_unlock_bh(&devlink_port->type_lock);
1339-
rtnl_unlock();
1342+
if (!rtnl_held)
1343+
rtnl_unlock();
13401344
nla_put_failure:
13411345
genlmsg_cancel(msg, hdr);
13421346
return -EMSGSIZE;
13431347
}
13441348

1345-
static void devlink_port_notify(struct devlink_port *devlink_port,
1346-
enum devlink_command cmd)
1349+
static void __devlink_port_notify(struct devlink_port *devlink_port,
1350+
enum devlink_command cmd, bool rtnl_held)
13471351
{
13481352
struct devlink *devlink = devlink_port->devlink;
13491353
struct sk_buff *msg;
@@ -1358,7 +1362,8 @@ static void devlink_port_notify(struct devlink_port *devlink_port,
13581362
if (!msg)
13591363
return;
13601364

1361-
err = devlink_nl_port_fill(msg, devlink_port, cmd, 0, 0, 0, NULL);
1365+
err = devlink_nl_port_fill(msg, devlink_port, cmd, 0, 0, 0, NULL,
1366+
rtnl_held);
13621367
if (err) {
13631368
nlmsg_free(msg);
13641369
return;
@@ -1368,6 +1373,12 @@ static void devlink_port_notify(struct devlink_port *devlink_port,
13681373
0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
13691374
}
13701375

1376+
static void devlink_port_notify(struct devlink_port *devlink_port,
1377+
enum devlink_command cmd)
1378+
{
1379+
__devlink_port_notify(devlink_port, cmd, false);
1380+
}
1381+
13711382
static void devlink_rate_notify(struct devlink_rate *devlink_rate,
13721383
enum devlink_command cmd)
13731384
{
@@ -1531,7 +1542,7 @@ static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb,
15311542

15321543
err = devlink_nl_port_fill(msg, devlink_port, DEVLINK_CMD_PORT_NEW,
15331544
info->snd_portid, info->snd_seq, 0,
1534-
info->extack);
1545+
info->extack, false);
15351546
if (err) {
15361547
nlmsg_free(msg);
15371548
return err;
@@ -1561,7 +1572,8 @@ static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg,
15611572
DEVLINK_CMD_NEW,
15621573
NETLINK_CB(cb->skb).portid,
15631574
cb->nlh->nlmsg_seq,
1564-
NLM_F_MULTI, cb->extack);
1575+
NLM_F_MULTI, cb->extack,
1576+
false);
15651577
if (err) {
15661578
devl_unlock(devlink);
15671579
devlink_put(devlink);
@@ -1773,7 +1785,8 @@ static int devlink_port_new_notify(struct devlink *devlink,
17731785
}
17741786

17751787
err = devlink_nl_port_fill(msg, devlink_port, DEVLINK_CMD_NEW,
1776-
info->snd_portid, info->snd_seq, 0, NULL);
1788+
info->snd_portid, info->snd_seq, 0, NULL,
1789+
false);
17771790
if (err)
17781791
goto out;
17791792

@@ -10033,7 +10046,7 @@ static void devlink_port_type_netdev_checks(struct devlink_port *devlink_port,
1003310046

1003410047
static void __devlink_port_type_set(struct devlink_port *devlink_port,
1003510048
enum devlink_port_type type,
10036-
void *type_dev)
10049+
void *type_dev, bool rtnl_held)
1003710050
{
1003810051
struct net_device *netdev = type_dev;
1003910052

@@ -10060,7 +10073,7 @@ static void __devlink_port_type_set(struct devlink_port *devlink_port,
1006010073
break;
1006110074
}
1006210075
spin_unlock_bh(&devlink_port->type_lock);
10063-
devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
10076+
__devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW, rtnl_held);
1006410077
}
1006510078

1006610079
/**
@@ -10077,7 +10090,8 @@ void devlink_port_type_eth_set(struct devlink_port *devlink_port,
1007710090
"devlink port type for port %d set to Ethernet without a software interface reference, device type not supported by the kernel?\n",
1007810091
devlink_port->index);
1007910092

10080-
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, netdev);
10093+
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, netdev,
10094+
false);
1008110095
}
1008210096
EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
1008310097

@@ -10090,7 +10104,8 @@ EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
1009010104
void devlink_port_type_ib_set(struct devlink_port *devlink_port,
1009110105
struct ib_device *ibdev)
1009210106
{
10093-
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_IB, ibdev);
10107+
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_IB, ibdev,
10108+
false);
1009410109
}
1009510110
EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
1009610111

@@ -10101,7 +10116,8 @@ EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
1010110116
*/
1010210117
void devlink_port_type_clear(struct devlink_port *devlink_port)
1010310118
{
10104-
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL);
10119+
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL,
10120+
false);
1010510121
}
1010610122
EXPORT_SYMBOL_GPL(devlink_port_type_clear);
1010710123

0 commit comments

Comments
 (0)