mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-04 04:04:19 +00:00
rtnetlink: Remove __rtnl_link_unregister().
rtnl_link_unregister() holds RTNL and calls __rtnl_link_unregister(), where we call synchronize_srcu() to wait inflight RTM_NEWLINK requests for per-netns RTNL. We put synchronize_srcu() in __rtnl_link_unregister() due to ifb.ko and dummy.ko. However, rtnl_newlink() will acquire SRCU before RTNL later in this series. Then, lockdep will detect the deadlock: rtnl_link_unregister() rtnl_newlink() ---- ---- lock(rtnl_mutex); lock(&ops->srcu); lock(rtnl_mutex); sync(&ops->srcu); To avoid the problem, we must call synchronize_srcu() before RTNL in rtnl_link_unregister(). As a preparation, let's remove __rtnl_link_unregister(). Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com> Link: https://patch.msgid.link/20241108004823.29419-2-kuniyu@amazon.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
7a3bcd39ae
commit
d5ec8d91f8
@ -166,6 +166,7 @@ static int __init dummy_init_one(void)
|
||||
|
||||
static int __init dummy_init_module(void)
|
||||
{
|
||||
bool need_unregister = false;
|
||||
int i, err = 0;
|
||||
|
||||
down_write(&pernet_ops_rwsem);
|
||||
@ -179,12 +180,15 @@ static int __init dummy_init_module(void)
|
||||
cond_resched();
|
||||
}
|
||||
if (err < 0)
|
||||
__rtnl_link_unregister(&dummy_link_ops);
|
||||
need_unregister = true;
|
||||
|
||||
out:
|
||||
rtnl_unlock();
|
||||
up_write(&pernet_ops_rwsem);
|
||||
|
||||
if (need_unregister)
|
||||
rtnl_link_unregister(&dummy_link_ops);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -424,6 +424,7 @@ static int __init ifb_init_one(int index)
|
||||
|
||||
static int __init ifb_init_module(void)
|
||||
{
|
||||
bool need_unregister = false;
|
||||
int i, err;
|
||||
|
||||
down_write(&pernet_ops_rwsem);
|
||||
@ -437,12 +438,15 @@ static int __init ifb_init_module(void)
|
||||
cond_resched();
|
||||
}
|
||||
if (err)
|
||||
__rtnl_link_unregister(&ifb_link_ops);
|
||||
need_unregister = true;
|
||||
|
||||
out:
|
||||
rtnl_unlock();
|
||||
up_write(&pernet_ops_rwsem);
|
||||
|
||||
if (need_unregister)
|
||||
rtnl_link_unregister(&ifb_link_ops);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,6 @@ struct rtnl_link_ops {
|
||||
};
|
||||
|
||||
int __rtnl_link_register(struct rtnl_link_ops *ops);
|
||||
void __rtnl_link_unregister(struct rtnl_link_ops *ops);
|
||||
|
||||
int rtnl_link_register(struct rtnl_link_ops *ops);
|
||||
void rtnl_link_unregister(struct rtnl_link_ops *ops);
|
||||
|
@ -568,27 +568,6 @@ static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops)
|
||||
unregister_netdevice_many(&list_kill);
|
||||
}
|
||||
|
||||
/**
|
||||
* __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
|
||||
* @ops: struct rtnl_link_ops * to unregister
|
||||
*
|
||||
* The caller must hold the rtnl_mutex and guarantee net_namespace_list
|
||||
* integrity (hold pernet_ops_rwsem for writing to close the race
|
||||
* with setup_net() and cleanup_net()).
|
||||
*/
|
||||
void __rtnl_link_unregister(struct rtnl_link_ops *ops)
|
||||
{
|
||||
struct net *net;
|
||||
|
||||
list_del_rcu(&ops->list);
|
||||
synchronize_srcu(&ops->srcu);
|
||||
cleanup_srcu_struct(&ops->srcu);
|
||||
|
||||
for_each_net(net)
|
||||
__rtnl_kill_links(net, ops);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__rtnl_link_unregister);
|
||||
|
||||
/* Return with the rtnl_lock held when there are no network
|
||||
* devices unregistering in any network namespace.
|
||||
*/
|
||||
@ -617,10 +596,19 @@ static void rtnl_lock_unregistering_all(void)
|
||||
*/
|
||||
void rtnl_link_unregister(struct rtnl_link_ops *ops)
|
||||
{
|
||||
struct net *net;
|
||||
|
||||
/* Close the race with setup_net() and cleanup_net() */
|
||||
down_write(&pernet_ops_rwsem);
|
||||
rtnl_lock_unregistering_all();
|
||||
__rtnl_link_unregister(ops);
|
||||
|
||||
list_del_rcu(&ops->list);
|
||||
synchronize_srcu(&ops->srcu);
|
||||
cleanup_srcu_struct(&ops->srcu);
|
||||
|
||||
for_each_net(net)
|
||||
__rtnl_kill_links(net, ops);
|
||||
|
||||
rtnl_unlock();
|
||||
up_write(&pernet_ops_rwsem);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user