mpls: no longer hold RTNL in mpls_netconf_dump_devconf()
BugLink: https://bugs.launchpad.net/bugs/2097393 [ Upstream commit e0f89d2864b062b027196925ea19f94b2ce50d6a ] - Use for_each_netdev_dump() to no longer rely on net->dev_index_head hash table. - No longer care of net->dev_base_seq - Fix return value at the end of a dump, so that NLMSG_DONE can be appended to current skb, saving one recvmsg() system call. - No longer grab RTNL, RCU protection is enough, afer adding one READ_ONCE(mdev->input_enabled) in mpls_netconf_fill_devconf() Signed-off-by: Eric Dumazet <edumazet@google.com> Link: https://lore.kernel.org/r/20240410111951.2673193-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Stable-dep-of: 5be2062e3080 ("mpls: Handle error of rtnl_register_module().") Signed-off-by: Sasha Levin <sashal@kernel.org> [diewald: adjusted becase we already applied follow-up commit 5be2062e3080e mpls: Handle error of rtnl_register_module().] Signed-off-by: Manuel Diewald <manuel.diewald@canonical.com> Signed-off-by: Koichiro Den <koichiro.den@canonical.com>
This commit is contained in:
committed by
Mehmet Basaran
parent
bdcb102517
commit
e9dd6b5c8c
+21
-37
@@ -1154,7 +1154,7 @@ static int mpls_netconf_fill_devconf(struct sk_buff *skb, struct mpls_dev *mdev,
|
||||
|
||||
if ((all || type == NETCONFA_INPUT) &&
|
||||
nla_put_s32(skb, NETCONFA_INPUT,
|
||||
mdev->input_enabled) < 0)
|
||||
READ_ONCE(mdev->input_enabled)) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
nlmsg_end(skb, nlh);
|
||||
@@ -1303,11 +1303,12 @@ static int mpls_netconf_dump_devconf(struct sk_buff *skb,
|
||||
{
|
||||
const struct nlmsghdr *nlh = cb->nlh;
|
||||
struct net *net = sock_net(skb->sk);
|
||||
struct hlist_head *head;
|
||||
struct {
|
||||
unsigned long ifindex;
|
||||
} *ctx = (void *)cb->ctx;
|
||||
struct net_device *dev;
|
||||
struct mpls_dev *mdev;
|
||||
int idx, s_idx;
|
||||
int h, s_h;
|
||||
int err = 0;
|
||||
|
||||
if (cb->strict_check) {
|
||||
struct netlink_ext_ack *extack = cb->extack;
|
||||
@@ -1324,40 +1325,23 @@ static int mpls_netconf_dump_devconf(struct sk_buff *skb,
|
||||
}
|
||||
}
|
||||
|
||||
s_h = cb->args[0];
|
||||
s_idx = idx = cb->args[1];
|
||||
|
||||
for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
|
||||
idx = 0;
|
||||
head = &net->dev_index_head[h];
|
||||
rcu_read_lock();
|
||||
cb->seq = net->dev_base_seq;
|
||||
hlist_for_each_entry_rcu(dev, head, index_hlist) {
|
||||
if (idx < s_idx)
|
||||
goto cont;
|
||||
mdev = mpls_dev_get(dev);
|
||||
if (!mdev)
|
||||
goto cont;
|
||||
if (mpls_netconf_fill_devconf(skb, mdev,
|
||||
NETLINK_CB(cb->skb).portid,
|
||||
nlh->nlmsg_seq,
|
||||
RTM_NEWNETCONF,
|
||||
NLM_F_MULTI,
|
||||
NETCONFA_ALL) < 0) {
|
||||
rcu_read_unlock();
|
||||
goto done;
|
||||
}
|
||||
nl_dump_check_consistent(cb, nlmsg_hdr(skb));
|
||||
cont:
|
||||
idx++;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
rcu_read_lock();
|
||||
for_each_netdev_dump(net, dev, ctx->ifindex) {
|
||||
mdev = mpls_dev_get(dev);
|
||||
if (!mdev)
|
||||
continue;
|
||||
err = mpls_netconf_fill_devconf(skb, mdev,
|
||||
NETLINK_CB(cb->skb).portid,
|
||||
nlh->nlmsg_seq,
|
||||
RTM_NEWNETCONF,
|
||||
NLM_F_MULTI,
|
||||
NETCONFA_ALL);
|
||||
if (err < 0)
|
||||
break;
|
||||
}
|
||||
done:
|
||||
cb->args[0] = h;
|
||||
cb->args[1] = idx;
|
||||
rcu_read_unlock();
|
||||
|
||||
return skb->len;
|
||||
return err;
|
||||
}
|
||||
|
||||
#define MPLS_PERDEV_SYSCTL_OFFSET(field) \
|
||||
@@ -2751,7 +2735,7 @@ static const struct rtnl_msg_handler mpls_rtnl_msg_handlers[] __initdata_or_modu
|
||||
{THIS_MODULE, PF_MPLS, RTM_GETROUTE, mpls_getroute, mpls_dump_routes, 0},
|
||||
{THIS_MODULE, PF_MPLS, RTM_GETNETCONF,
|
||||
mpls_netconf_get_devconf, mpls_netconf_dump_devconf,
|
||||
0},
|
||||
RTNL_FLAG_DUMP_UNLOCKED},
|
||||
};
|
||||
|
||||
static int __init mpls_init(void)
|
||||
|
||||
Reference in New Issue
Block a user