* [PATCH net-next] net: move replay logic to tc_modify_qdisc
@ 2025-03-25 17:54 Stanislav Fomichev
2025-03-25 18:01 ` Eric Dumazet
2025-03-27 18:50 ` patchwork-bot+netdevbpf
0 siblings, 2 replies; 3+ messages in thread
From: Stanislav Fomichev @ 2025-03-25 17:54 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, kuba, pabeni, linux-kernel, jhs, xiyou.wangcong,
jiri, horms, sdf
Eric reports that by the time we call netdev_lock_ops after
rtnl_unlock/rtnl_lock, the dev might point to an invalid device.
As suggested by Jakub in [0], move rtnl lock/unlock and request_module
outside of qdisc_create. This removes extra complexity with relocking
the netdev.
0: https://lore.kernel.org/netdev/20250325032803.1542c15e@kernel.org/
Fixes: a0527ee2df3f ("net: hold netdev instance lock during qdisc ndo_setup_tc")
Reported-by: Eric Dumazet <edumazet@google.com>
Link: https://lore.kernel.org/netdev/20250305163732.2766420-1-sdf@fomichev.me/T/#me8dfd778ea4c4463acab55644e3f9836bc608771
Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
---
net/sched/sch_api.c | 73 +++++++++++++++++----------------------------
1 file changed, 27 insertions(+), 46 deletions(-)
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index aef39f6dc6a8..fcb07c03117e 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1268,38 +1268,8 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
struct qdisc_size_table *stab;
ops = qdisc_lookup_ops(kind);
-#ifdef CONFIG_MODULES
- if (ops == NULL && kind != NULL) {
- char name[IFNAMSIZ];
- if (nla_strscpy(name, kind, IFNAMSIZ) >= 0) {
- /* We dropped the RTNL semaphore in order to
- * perform the module load. So, even if we
- * succeeded in loading the module we have to
- * tell the caller to replay the request. We
- * indicate this using -EAGAIN.
- * We replay the request because the device may
- * go away in the mean time.
- */
- netdev_unlock_ops(dev);
- rtnl_unlock();
- request_module(NET_SCH_ALIAS_PREFIX "%s", name);
- rtnl_lock();
- netdev_lock_ops(dev);
- ops = qdisc_lookup_ops(kind);
- if (ops != NULL) {
- /* We will try again qdisc_lookup_ops,
- * so don't keep a reference.
- */
- module_put(ops->owner);
- err = -EAGAIN;
- goto err_out;
- }
- }
- }
-#endif
-
- err = -ENOENT;
if (!ops) {
+ err = -ENOENT;
NL_SET_ERR_MSG(extack, "Specified qdisc kind is unknown");
goto err_out;
}
@@ -1624,8 +1594,7 @@ static int __tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
struct netlink_ext_ack *extack,
struct net_device *dev,
struct nlattr *tca[TCA_MAX + 1],
- struct tcmsg *tcm,
- bool *replay)
+ struct tcmsg *tcm)
{
struct Qdisc *q = NULL;
struct Qdisc *p = NULL;
@@ -1790,13 +1759,8 @@ static int __tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
tcm->tcm_parent, tcm->tcm_handle,
tca, &err, extack);
}
- if (q == NULL) {
- if (err == -EAGAIN) {
- *replay = true;
- return 0;
- }
+ if (!q)
return err;
- }
graft:
err = qdisc_graft(dev, p, skb, n, clid, q, NULL, extack);
@@ -1809,6 +1773,27 @@ static int __tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
return 0;
}
+static void request_qdisc_module(struct nlattr *kind)
+{
+ struct Qdisc_ops *ops;
+ char name[IFNAMSIZ];
+
+ if (!kind)
+ return;
+
+ ops = qdisc_lookup_ops(kind);
+ if (ops) {
+ module_put(ops->owner);
+ return;
+ }
+
+ if (nla_strscpy(name, kind, IFNAMSIZ) >= 0) {
+ rtnl_unlock();
+ request_module(NET_SCH_ALIAS_PREFIX "%s", name);
+ rtnl_lock();
+ }
+}
+
/*
* Create/change qdisc.
*/
@@ -1819,27 +1804,23 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
struct nlattr *tca[TCA_MAX + 1];
struct net_device *dev;
struct tcmsg *tcm;
- bool replay;
int err;
-replay:
- /* Reinit, just in case something touches this. */
err = nlmsg_parse_deprecated(n, sizeof(*tcm), tca, TCA_MAX,
rtm_tca_policy, extack);
if (err < 0)
return err;
+ request_qdisc_module(tca[TCA_KIND]);
+
tcm = nlmsg_data(n);
dev = __dev_get_by_index(net, tcm->tcm_ifindex);
if (!dev)
return -ENODEV;
- replay = false;
netdev_lock_ops(dev);
- err = __tc_modify_qdisc(skb, n, extack, dev, tca, tcm, &replay);
+ err = __tc_modify_qdisc(skb, n, extack, dev, tca, tcm);
netdev_unlock_ops(dev);
- if (replay)
- goto replay;
return err;
}
--
2.48.1
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH net-next] net: move replay logic to tc_modify_qdisc
2025-03-25 17:54 [PATCH net-next] net: move replay logic to tc_modify_qdisc Stanislav Fomichev
@ 2025-03-25 18:01 ` Eric Dumazet
2025-03-27 18:50 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: Eric Dumazet @ 2025-03-25 18:01 UTC (permalink / raw)
To: Stanislav Fomichev
Cc: netdev, davem, kuba, pabeni, linux-kernel, jhs, xiyou.wangcong,
jiri, horms
On Tue, Mar 25, 2025 at 6:54 PM Stanislav Fomichev <sdf@fomichev.me> wrote:
>
> Eric reports that by the time we call netdev_lock_ops after
> rtnl_unlock/rtnl_lock, the dev might point to an invalid device.
> As suggested by Jakub in [0], move rtnl lock/unlock and request_module
> outside of qdisc_create. This removes extra complexity with relocking
> the netdev.
>
> 0: https://lore.kernel.org/netdev/20250325032803.1542c15e@kernel.org/
>
> Fixes: a0527ee2df3f ("net: hold netdev instance lock during qdisc ndo_setup_tc")
> Reported-by: Eric Dumazet <edumazet@google.com>
> Link: https://lore.kernel.org/netdev/20250305163732.2766420-1-sdf@fomichev.me/T/#me8dfd778ea4c4463acab55644e3f9836bc608771
> Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
Nice, thank you !
Reviewed-by: Eric Dumazet <edumazet@google.com>
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH net-next] net: move replay logic to tc_modify_qdisc
2025-03-25 17:54 [PATCH net-next] net: move replay logic to tc_modify_qdisc Stanislav Fomichev
2025-03-25 18:01 ` Eric Dumazet
@ 2025-03-27 18:50 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: patchwork-bot+netdevbpf @ 2025-03-27 18:50 UTC (permalink / raw)
To: Stanislav Fomichev
Cc: netdev, davem, edumazet, kuba, pabeni, linux-kernel, jhs,
xiyou.wangcong, jiri, horms
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Tue, 25 Mar 2025 10:54:27 -0700 you wrote:
> Eric reports that by the time we call netdev_lock_ops after
> rtnl_unlock/rtnl_lock, the dev might point to an invalid device.
> As suggested by Jakub in [0], move rtnl lock/unlock and request_module
> outside of qdisc_create. This removes extra complexity with relocking
> the netdev.
>
> 0: https://lore.kernel.org/netdev/20250325032803.1542c15e@kernel.org/
>
> [...]
Here is the summary with links:
- [net-next] net: move replay logic to tc_modify_qdisc
https://git.kernel.org/netdev/net/c/2eb6c6a34cb1
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-03-27 18:49 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-25 17:54 [PATCH net-next] net: move replay logic to tc_modify_qdisc Stanislav Fomichev
2025-03-25 18:01 ` Eric Dumazet
2025-03-27 18:50 ` patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).