mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-05-15 12:12:53 +00:00
net: hold netdev instance lock during qdisc ndo_setup_tc
Qdisc operations that can lead to ndo_setup_tc might need to have an instance lock. Add netdev_lock_ops/netdev_unlock_ops invocations for all psched_rtnl_msg_handlers operations. Cc: Cong Wang <xiyou.wangcong@gmail.com> Cc: Jiri Pirko <jiri@resnulli.us> Cc: Saeed Mahameed <saeed@kernel.org> Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com> Signed-off-by: Stanislav Fomichev <sdf@fomichev.me> Link: https://patch.msgid.link/20250305163732.2766420-5-sdf@fomichev.me Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
7c79cff955
commit
a0527ee2df
1 changed files with 24 additions and 4 deletions
|
@ -1279,9 +1279,11 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
|
||||||
* We replay the request because the device may
|
* We replay the request because the device may
|
||||||
* go away in the mean time.
|
* go away in the mean time.
|
||||||
*/
|
*/
|
||||||
|
netdev_unlock_ops(dev);
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
request_module(NET_SCH_ALIAS_PREFIX "%s", name);
|
request_module(NET_SCH_ALIAS_PREFIX "%s", name);
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
|
netdev_lock_ops(dev);
|
||||||
ops = qdisc_lookup_ops(kind);
|
ops = qdisc_lookup_ops(kind);
|
||||||
if (ops != NULL) {
|
if (ops != NULL) {
|
||||||
/* We will try again qdisc_lookup_ops,
|
/* We will try again qdisc_lookup_ops,
|
||||||
|
@ -1591,7 +1593,11 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
return __tc_get_qdisc(skb, n, extack, dev, tca, tcm);
|
netdev_lock_ops(dev);
|
||||||
|
err = __tc_get_qdisc(skb, n, extack, dev, tca, tcm);
|
||||||
|
netdev_unlock_ops(dev);
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool req_create_or_replace(struct nlmsghdr *n)
|
static bool req_create_or_replace(struct nlmsghdr *n)
|
||||||
|
@ -1828,7 +1834,9 @@ replay:
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
replay = false;
|
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, &replay);
|
||||||
|
netdev_unlock_ops(dev);
|
||||||
if (replay)
|
if (replay)
|
||||||
goto replay;
|
goto replay;
|
||||||
|
|
||||||
|
@ -1919,17 +1927,23 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
|
||||||
s_q_idx = 0;
|
s_q_idx = 0;
|
||||||
q_idx = 0;
|
q_idx = 0;
|
||||||
|
|
||||||
|
netdev_lock_ops(dev);
|
||||||
if (tc_dump_qdisc_root(rtnl_dereference(dev->qdisc),
|
if (tc_dump_qdisc_root(rtnl_dereference(dev->qdisc),
|
||||||
skb, cb, &q_idx, s_q_idx,
|
skb, cb, &q_idx, s_q_idx,
|
||||||
true, tca[TCA_DUMP_INVISIBLE]) < 0)
|
true, tca[TCA_DUMP_INVISIBLE]) < 0) {
|
||||||
|
netdev_unlock_ops(dev);
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
dev_queue = dev_ingress_queue(dev);
|
dev_queue = dev_ingress_queue(dev);
|
||||||
if (dev_queue &&
|
if (dev_queue &&
|
||||||
tc_dump_qdisc_root(rtnl_dereference(dev_queue->qdisc_sleeping),
|
tc_dump_qdisc_root(rtnl_dereference(dev_queue->qdisc_sleeping),
|
||||||
skb, cb, &q_idx, s_q_idx, false,
|
skb, cb, &q_idx, s_q_idx, false,
|
||||||
tca[TCA_DUMP_INVISIBLE]) < 0)
|
tca[TCA_DUMP_INVISIBLE]) < 0) {
|
||||||
|
netdev_unlock_ops(dev);
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
|
netdev_unlock_ops(dev);
|
||||||
|
|
||||||
cont:
|
cont:
|
||||||
idx++;
|
idx++;
|
||||||
|
@ -2308,7 +2322,11 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n,
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
return __tc_ctl_tclass(skb, n, extack, dev, tca, tcm);
|
netdev_lock_ops(dev);
|
||||||
|
err = __tc_ctl_tclass(skb, n, extack, dev, tca, tcm);
|
||||||
|
netdev_unlock_ops(dev);
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct qdisc_dump_args {
|
struct qdisc_dump_args {
|
||||||
|
@ -2426,7 +2444,9 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
netdev_lock_ops(dev);
|
||||||
err = __tc_dump_tclass(skb, cb, tcm, dev);
|
err = __tc_dump_tclass(skb, cb, tcm, dev);
|
||||||
|
netdev_unlock_ops(dev);
|
||||||
|
|
||||||
dev_put(dev);
|
dev_put(dev);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue