aboutsummaryrefslogtreecommitdiffstats
path: root/net/mptcp/pm.c
diff options
context:
space:
mode:
authorGeliang Tang <[email protected]>2025-02-07 13:59:30 +0000
committerPaolo Abeni <[email protected]>2025-02-11 11:46:37 +0000
commit8556f4aecc9a0620c1e411d6da1fe232d1c14138 (patch)
tree97de20205490ca7d76123f2b37517a8267124e36 /net/mptcp/pm.c
parentmptcp: pm: add id parameter for get_addr (diff)
downloadkernel-8556f4aecc9a0620c1e411d6da1fe232d1c14138.tar.gz
kernel-8556f4aecc9a0620c1e411d6da1fe232d1c14138.zip
mptcp: pm: reuse sending nlmsg code in get_addr
The netlink messages are sent both in mptcp_pm_nl_get_addr() and mptcp_userspace_pm_get_addr(), this makes the code somewhat repetitive. This is because the netlink PM and userspace PM use different locks to protect the address entry that needs to be sent via the netlink message. The former uses rcu read lock, and the latter uses msk->pm.lock. The current get_addr() flow looks like this: lock(); entry = get_entry(); send_nlmsg(entry); unlock(); After holding the lock, get the entry from the list, send the entry, and finally release the lock. This patch changes the process by getting the entry while holding the lock, then making a copy of the entry so that the lock can be released. Finally, the copy of the entry is sent without locking: lock(); entry = get_entry(); *copy = *entry; unlock(); send_nlmsg(copy); This way we can reuse the send_nlmsg() code in get_addr() interfaces between the netlink PM and userspace PM. They only need to implement their own get_addr() interfaces to hold the different locks, get the entry from the different lists, then release the locks. Signed-off-by: Geliang Tang <[email protected]> Reviewed-by: Matthieu Baerts (NGI0) <[email protected]> Signed-off-by: Matthieu Baerts (NGI0) <[email protected]> Reviewed-by: Simon Horman <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
Diffstat (limited to 'net/mptcp/pm.c')
-rw-r--r--net/mptcp/pm.c39
1 files changed, 35 insertions, 4 deletions
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index caf5bfc3cd1d..ba22d17c1451 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -434,17 +434,20 @@ bool mptcp_pm_is_backup(struct mptcp_sock *msk, struct sock_common *skc)
return mptcp_pm_nl_is_backup(msk, &skc_local);
}
-static int mptcp_pm_get_addr(u8 id, struct genl_info *info)
+static int mptcp_pm_get_addr(u8 id, struct mptcp_pm_addr_entry *addr,
+ struct genl_info *info)
{
if (info->attrs[MPTCP_PM_ATTR_TOKEN])
- return mptcp_userspace_pm_get_addr(id, info);
- return mptcp_pm_nl_get_addr(id, info);
+ return mptcp_userspace_pm_get_addr(id, addr, info);
+ return mptcp_pm_nl_get_addr(id, addr, info);
}
int mptcp_pm_nl_get_addr_doit(struct sk_buff *skb, struct genl_info *info)
{
struct mptcp_pm_addr_entry addr;
struct nlattr *attr;
+ struct sk_buff *msg;
+ void *reply;
int ret;
if (GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ENDPOINT_ADDR))
@@ -455,7 +458,35 @@ int mptcp_pm_nl_get_addr_doit(struct sk_buff *skb, struct genl_info *info)
if (ret < 0)
return ret;
- return mptcp_pm_get_addr(addr.addr.id, info);
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ reply = genlmsg_put_reply(msg, info, &mptcp_genl_family, 0,
+ info->genlhdr->cmd);
+ if (!reply) {
+ GENL_SET_ERR_MSG(info, "not enough space in Netlink message");
+ ret = -EMSGSIZE;
+ goto fail;
+ }
+
+ ret = mptcp_pm_get_addr(addr.addr.id, &addr, info);
+ if (ret) {
+ NL_SET_ERR_MSG_ATTR(info->extack, attr, "address not found");
+ goto fail;
+ }
+
+ ret = mptcp_nl_fill_addr(msg, &addr);
+ if (ret)
+ goto fail;
+
+ genlmsg_end(msg, reply);
+ ret = genlmsg_reply(msg, info);
+ return ret;
+
+fail:
+ nlmsg_free(msg);
+ return ret;
}
static int mptcp_pm_dump_addr(struct sk_buff *msg, struct netlink_callback *cb)