Skip to content

Commit fed176b

Browse files
q2venkuba-moo
authored andcommitted
net: Add ops_undo_single for module load/unload.
If ops_init() fails while loading a module or we unload the module, free_exit_list() rolls back the changes. The rollback sequence is the same as ops_undo_list(). The ops is already removed from pernet_list before calling free_exit_list(). If we link the ops to a temporary list, we can reuse ops_undo_list(). Let's add a wrapper of ops_undo_list() and use it instead of free_exit_list(). Now, we have the central place to roll back ops_init(). Signed-off-by: Kuniyuki Iwashima <[email protected]> Reviewed-by: Sabrina Dubroca <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent e333b1c commit fed176b

File tree

1 file changed

+24
-30
lines changed

1 file changed

+24
-30
lines changed

net/core/net_namespace.c

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,17 @@ static void ops_undo_list(const struct list_head *ops_list,
235235
ops_free_list(ops, net_exit_list);
236236
}
237237

238+
static void ops_undo_single(struct pernet_operations *ops,
239+
struct list_head *net_exit_list)
240+
{
241+
bool hold_rtnl = !!ops->exit_batch_rtnl;
242+
LIST_HEAD(ops_list);
243+
244+
list_add(&ops->list, &ops_list);
245+
ops_undo_list(&ops_list, NULL, net_exit_list, false, hold_rtnl);
246+
list_del(&ops->list);
247+
}
248+
238249
/* should be called with nsid_lock held */
239250
static int alloc_netid(struct net *net, struct net *peer, int reqid)
240251
{
@@ -1235,31 +1246,13 @@ void __init net_ns_init(void)
12351246
rtnl_register_many(net_ns_rtnl_msg_handlers);
12361247
}
12371248

1238-
static void free_exit_list(struct pernet_operations *ops, struct list_head *net_exit_list)
1239-
{
1240-
ops_pre_exit_list(ops, net_exit_list);
1241-
synchronize_rcu();
1242-
1243-
if (ops->exit_batch_rtnl) {
1244-
LIST_HEAD(dev_kill_list);
1245-
1246-
rtnl_lock();
1247-
ops->exit_batch_rtnl(net_exit_list, &dev_kill_list);
1248-
unregister_netdevice_many(&dev_kill_list);
1249-
rtnl_unlock();
1250-
}
1251-
ops_exit_list(ops, net_exit_list);
1252-
1253-
ops_free_list(ops, net_exit_list);
1254-
}
1255-
12561249
#ifdef CONFIG_NET_NS
12571250
static int __register_pernet_operations(struct list_head *list,
12581251
struct pernet_operations *ops)
12591252
{
1253+
LIST_HEAD(net_exit_list);
12601254
struct net *net;
12611255
int error;
1262-
LIST_HEAD(net_exit_list);
12631256

12641257
list_add_tail(&ops->list, list);
12651258
if (ops->init || ops->id) {
@@ -1278,44 +1271,45 @@ static int __register_pernet_operations(struct list_head *list,
12781271
out_undo:
12791272
/* If I have an error cleanup all namespaces I initialized */
12801273
list_del(&ops->list);
1281-
free_exit_list(ops, &net_exit_list);
1274+
ops_undo_single(ops, &net_exit_list);
12821275
return error;
12831276
}
12841277

12851278
static void __unregister_pernet_operations(struct pernet_operations *ops)
12861279
{
1287-
struct net *net;
12881280
LIST_HEAD(net_exit_list);
1281+
struct net *net;
12891282

1290-
list_del(&ops->list);
12911283
/* See comment in __register_pernet_operations() */
12921284
for_each_net(net)
12931285
list_add_tail(&net->exit_list, &net_exit_list);
12941286

1295-
free_exit_list(ops, &net_exit_list);
1287+
list_del(&ops->list);
1288+
ops_undo_single(ops, &net_exit_list);
12961289
}
12971290

12981291
#else
12991292

13001293
static int __register_pernet_operations(struct list_head *list,
13011294
struct pernet_operations *ops)
13021295
{
1303-
if (!init_net_initialized) {
1304-
list_add_tail(&ops->list, list);
1296+
list_add_tail(&ops->list, list);
1297+
1298+
if (!init_net_initialized)
13051299
return 0;
1306-
}
13071300

13081301
return ops_init(ops, &init_net);
13091302
}
13101303

13111304
static void __unregister_pernet_operations(struct pernet_operations *ops)
13121305
{
1313-
if (!init_net_initialized) {
1314-
list_del(&ops->list);
1315-
} else {
1306+
list_del(&ops->list);
1307+
1308+
if (init_net_initialized) {
13161309
LIST_HEAD(net_exit_list);
1310+
13171311
list_add(&init_net.exit_list, &net_exit_list);
1318-
free_exit_list(ops, &net_exit_list);
1312+
ops_undo_single(ops, &net_exit_list);
13191313
}
13201314
}
13211315

0 commit comments

Comments
 (0)