mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 03:53:37 +02:00
ipmr: Convert ipmr_rtm_dumplink() to RCU.
net->ipv4.mr_tables is updated under RTNL and can be read safely under RCU. Once created, the multicast route tables are not removed until netns dismantle. ipmr_rtm_dumplink() does not need RTNL protection for ipmr_for_each_table() and ipmr_fill_table() if RCU is held. Even if mrt->maxvif changes concurrently, ipmr_fill_vif() returns true to continue dumping the next table. Let's convert it to RCU. Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Link: https://patch.msgid.link/20260228221800.1082070-4-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
261950e039
commit
402a8111d7
|
|
@ -2901,12 +2901,13 @@ static bool ipmr_fill_table(struct mr_table *mrt, struct sk_buff *skb)
|
|||
if (nla_put_u32(skb, IPMRA_TABLE_ID, mrt->id) ||
|
||||
nla_put_u32(skb, IPMRA_TABLE_CACHE_RES_QUEUE_LEN, queue_len) ||
|
||||
nla_put_s32(skb, IPMRA_TABLE_MROUTE_REG_VIF_NUM,
|
||||
mrt->mroute_reg_vif_num) ||
|
||||
READ_ONCE(mrt->mroute_reg_vif_num)) ||
|
||||
nla_put_u8(skb, IPMRA_TABLE_MROUTE_DO_ASSERT,
|
||||
mrt->mroute_do_assert) ||
|
||||
nla_put_u8(skb, IPMRA_TABLE_MROUTE_DO_PIM, mrt->mroute_do_pim) ||
|
||||
READ_ONCE(mrt->mroute_do_assert)) ||
|
||||
nla_put_u8(skb, IPMRA_TABLE_MROUTE_DO_PIM,
|
||||
READ_ONCE(mrt->mroute_do_pim)) ||
|
||||
nla_put_u8(skb, IPMRA_TABLE_MROUTE_DO_WRVIFWHOLE,
|
||||
mrt->mroute_do_wrvifwhole))
|
||||
READ_ONCE(mrt->mroute_do_wrvifwhole)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
@ -2919,7 +2920,7 @@ static bool ipmr_fill_vif(struct mr_table *mrt, u32 vifid, struct sk_buff *skb)
|
|||
struct vif_device *vif;
|
||||
|
||||
vif = &mrt->vif_table[vifid];
|
||||
vif_dev = rtnl_dereference(vif->dev);
|
||||
vif_dev = vif_dev_read(vif);
|
||||
/* if the VIF doesn't exist just continue */
|
||||
if (!vif_dev)
|
||||
return true;
|
||||
|
|
@ -2928,16 +2929,16 @@ static bool ipmr_fill_vif(struct mr_table *mrt, u32 vifid, struct sk_buff *skb)
|
|||
if (!vif_nest)
|
||||
return false;
|
||||
|
||||
if (nla_put_u32(skb, IPMRA_VIFA_IFINDEX, vif_dev->ifindex) ||
|
||||
if (nla_put_u32(skb, IPMRA_VIFA_IFINDEX, READ_ONCE(vif_dev->ifindex)) ||
|
||||
nla_put_u32(skb, IPMRA_VIFA_VIF_ID, vifid) ||
|
||||
nla_put_u16(skb, IPMRA_VIFA_FLAGS, vif->flags) ||
|
||||
nla_put_u64_64bit(skb, IPMRA_VIFA_BYTES_IN, vif->bytes_in,
|
||||
nla_put_u64_64bit(skb, IPMRA_VIFA_BYTES_IN, READ_ONCE(vif->bytes_in),
|
||||
IPMRA_VIFA_PAD) ||
|
||||
nla_put_u64_64bit(skb, IPMRA_VIFA_BYTES_OUT, vif->bytes_out,
|
||||
nla_put_u64_64bit(skb, IPMRA_VIFA_BYTES_OUT, READ_ONCE(vif->bytes_out),
|
||||
IPMRA_VIFA_PAD) ||
|
||||
nla_put_u64_64bit(skb, IPMRA_VIFA_PACKETS_IN, vif->pkt_in,
|
||||
nla_put_u64_64bit(skb, IPMRA_VIFA_PACKETS_IN, READ_ONCE(vif->pkt_in),
|
||||
IPMRA_VIFA_PAD) ||
|
||||
nla_put_u64_64bit(skb, IPMRA_VIFA_PACKETS_OUT, vif->pkt_out,
|
||||
nla_put_u64_64bit(skb, IPMRA_VIFA_PACKETS_OUT, READ_ONCE(vif->pkt_out),
|
||||
IPMRA_VIFA_PAD) ||
|
||||
nla_put_be32(skb, IPMRA_VIFA_LOCAL_ADDR, vif->local) ||
|
||||
nla_put_be32(skb, IPMRA_VIFA_REMOTE_ADDR, vif->remote)) {
|
||||
|
|
@ -2992,6 +2993,8 @@ static int ipmr_rtm_dumplink(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
s_t = cb->args[0];
|
||||
s_e = cb->args[1];
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
ipmr_for_each_table(mrt, net) {
|
||||
struct nlattr *vifs, *af;
|
||||
struct ifinfomsg *hdr;
|
||||
|
|
@ -3026,7 +3029,7 @@ static int ipmr_rtm_dumplink(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
nlmsg_end(skb, nlh);
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; i < mrt->maxvif; i++) {
|
||||
for (i = 0; i < READ_ONCE(mrt->maxvif); i++) {
|
||||
if (e < s_e)
|
||||
goto skip_entry;
|
||||
if (!ipmr_fill_vif(mrt, i, skb)) {
|
||||
|
|
@ -3048,6 +3051,8 @@ static int ipmr_rtm_dumplink(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
}
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
||||
cb->args[1] = e;
|
||||
cb->args[0] = t;
|
||||
|
||||
|
|
@ -3287,7 +3292,7 @@ static struct pernet_operations ipmr_net_ops = {
|
|||
|
||||
static const struct rtnl_msg_handler ipmr_rtnl_msg_handlers[] __initconst = {
|
||||
{.protocol = RTNL_FAMILY_IPMR, .msgtype = RTM_GETLINK,
|
||||
.dumpit = ipmr_rtm_dumplink},
|
||||
.dumpit = ipmr_rtm_dumplink, .flags = RTNL_FLAG_DUMP_UNLOCKED},
|
||||
{.protocol = RTNL_FAMILY_IPMR, .msgtype = RTM_NEWROUTE,
|
||||
.doit = ipmr_rtm_route},
|
||||
{.protocol = RTNL_FAMILY_IPMR, .msgtype = RTM_DELROUTE,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user