Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Kuniyuki Iwashima and committed by
Jakub Kicinski
402a8111 261950e0

+17 -12
+17 -12
net/ipv4/ipmr.c
··· 2901 2901 if (nla_put_u32(skb, IPMRA_TABLE_ID, mrt->id) || 2902 2902 nla_put_u32(skb, IPMRA_TABLE_CACHE_RES_QUEUE_LEN, queue_len) || 2903 2903 nla_put_s32(skb, IPMRA_TABLE_MROUTE_REG_VIF_NUM, 2904 - mrt->mroute_reg_vif_num) || 2904 + READ_ONCE(mrt->mroute_reg_vif_num)) || 2905 2905 nla_put_u8(skb, IPMRA_TABLE_MROUTE_DO_ASSERT, 2906 - mrt->mroute_do_assert) || 2907 - nla_put_u8(skb, IPMRA_TABLE_MROUTE_DO_PIM, mrt->mroute_do_pim) || 2906 + READ_ONCE(mrt->mroute_do_assert)) || 2907 + nla_put_u8(skb, IPMRA_TABLE_MROUTE_DO_PIM, 2908 + READ_ONCE(mrt->mroute_do_pim)) || 2908 2909 nla_put_u8(skb, IPMRA_TABLE_MROUTE_DO_WRVIFWHOLE, 2909 - mrt->mroute_do_wrvifwhole)) 2910 + READ_ONCE(mrt->mroute_do_wrvifwhole))) 2910 2911 return false; 2911 2912 2912 2913 return true; ··· 2920 2919 struct vif_device *vif; 2921 2920 2922 2921 vif = &mrt->vif_table[vifid]; 2923 - vif_dev = rtnl_dereference(vif->dev); 2922 + vif_dev = vif_dev_read(vif); 2924 2923 /* if the VIF doesn't exist just continue */ 2925 2924 if (!vif_dev) 2926 2925 return true; ··· 2929 2928 if (!vif_nest) 2930 2929 return false; 2931 2930 2932 - if (nla_put_u32(skb, IPMRA_VIFA_IFINDEX, vif_dev->ifindex) || 2931 + if (nla_put_u32(skb, IPMRA_VIFA_IFINDEX, READ_ONCE(vif_dev->ifindex)) || 2933 2932 nla_put_u32(skb, IPMRA_VIFA_VIF_ID, vifid) || 2934 2933 nla_put_u16(skb, IPMRA_VIFA_FLAGS, vif->flags) || 2935 - nla_put_u64_64bit(skb, IPMRA_VIFA_BYTES_IN, vif->bytes_in, 2934 + nla_put_u64_64bit(skb, IPMRA_VIFA_BYTES_IN, READ_ONCE(vif->bytes_in), 2936 2935 IPMRA_VIFA_PAD) || 2937 - nla_put_u64_64bit(skb, IPMRA_VIFA_BYTES_OUT, vif->bytes_out, 2936 + nla_put_u64_64bit(skb, IPMRA_VIFA_BYTES_OUT, READ_ONCE(vif->bytes_out), 2938 2937 IPMRA_VIFA_PAD) || 2939 - nla_put_u64_64bit(skb, IPMRA_VIFA_PACKETS_IN, vif->pkt_in, 2938 + nla_put_u64_64bit(skb, IPMRA_VIFA_PACKETS_IN, READ_ONCE(vif->pkt_in), 2940 2939 IPMRA_VIFA_PAD) || 2941 - nla_put_u64_64bit(skb, IPMRA_VIFA_PACKETS_OUT, vif->pkt_out, 2940 + nla_put_u64_64bit(skb, IPMRA_VIFA_PACKETS_OUT, READ_ONCE(vif->pkt_out), 2942 2941 IPMRA_VIFA_PAD) || 2943 2942 nla_put_be32(skb, IPMRA_VIFA_LOCAL_ADDR, vif->local) || 2944 2943 nla_put_be32(skb, IPMRA_VIFA_REMOTE_ADDR, vif->remote)) { ··· 2993 2992 s_t = cb->args[0]; 2994 2993 s_e = cb->args[1]; 2995 2994 2995 + rcu_read_lock(); 2996 + 2996 2997 ipmr_for_each_table(mrt, net) { 2997 2998 struct nlattr *vifs, *af; 2998 2999 struct ifinfomsg *hdr; ··· 3029 3026 nlmsg_end(skb, nlh); 3030 3027 goto out; 3031 3028 } 3032 - for (i = 0; i < mrt->maxvif; i++) { 3029 + for (i = 0; i < READ_ONCE(mrt->maxvif); i++) { 3033 3030 if (e < s_e) 3034 3031 goto skip_entry; 3035 3032 if (!ipmr_fill_vif(mrt, i, skb)) { ··· 3051 3048 } 3052 3049 3053 3050 out: 3051 + rcu_read_unlock(); 3052 + 3054 3053 cb->args[1] = e; 3055 3054 cb->args[0] = t; 3056 3055 ··· 3292 3287 3293 3288 static const struct rtnl_msg_handler ipmr_rtnl_msg_handlers[] __initconst = { 3294 3289 {.protocol = RTNL_FAMILY_IPMR, .msgtype = RTM_GETLINK, 3295 - .dumpit = ipmr_rtm_dumplink}, 3290 + .dumpit = ipmr_rtm_dumplink, .flags = RTNL_FLAG_DUMP_UNLOCKED}, 3296 3291 {.protocol = RTNL_FAMILY_IPMR, .msgtype = RTM_NEWROUTE, 3297 3292 .doit = ipmr_rtm_route}, 3298 3293 {.protocol = RTNL_FAMILY_IPMR, .msgtype = RTM_DELROUTE,