Commit 485ac57b authored by Alexey Dobriyan's avatar Alexey Dobriyan Committed by David S. Miller

netns: add register_pernet_gen_subsys/unregister_pernet_gen_subsys

netns ops which are registered with register_pernet_gen_device() are
shutdown strictly before those which are registered with
register_pernet_subsys(). Sometimes this leads to opposite (read: buggy)
shutdown ordering between two modules.

Add register_pernet_gen_subsys()/unregister_pernet_gen_subsys() for modules
which aren't elite enough for entry in struct net, and which can't use
register_pernet_gen_device(). PPTP conntracking module is such one.
Signed-off-by: default avatarAlexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ad1d967c
...@@ -214,6 +214,8 @@ struct pernet_operations { ...@@ -214,6 +214,8 @@ struct pernet_operations {
extern int register_pernet_subsys(struct pernet_operations *); extern int register_pernet_subsys(struct pernet_operations *);
extern void unregister_pernet_subsys(struct pernet_operations *); extern void unregister_pernet_subsys(struct pernet_operations *);
extern int register_pernet_gen_subsys(int *id, struct pernet_operations *);
extern void unregister_pernet_gen_subsys(int id, struct pernet_operations *);
extern int register_pernet_device(struct pernet_operations *); extern int register_pernet_device(struct pernet_operations *);
extern void unregister_pernet_device(struct pernet_operations *); extern void unregister_pernet_device(struct pernet_operations *);
extern int register_pernet_gen_device(int *id, struct pernet_operations *); extern int register_pernet_gen_device(int *id, struct pernet_operations *);
......
...@@ -325,6 +325,38 @@ void unregister_pernet_subsys(struct pernet_operations *module) ...@@ -325,6 +325,38 @@ void unregister_pernet_subsys(struct pernet_operations *module)
} }
EXPORT_SYMBOL_GPL(unregister_pernet_subsys); EXPORT_SYMBOL_GPL(unregister_pernet_subsys);
int register_pernet_gen_subsys(int *id, struct pernet_operations *ops)
{
int rv;
mutex_lock(&net_mutex);
again:
rv = ida_get_new_above(&net_generic_ids, 1, id);
if (rv < 0) {
if (rv == -EAGAIN) {
ida_pre_get(&net_generic_ids, GFP_KERNEL);
goto again;
}
goto out;
}
rv = register_pernet_operations(first_device, ops);
if (rv < 0)
ida_remove(&net_generic_ids, *id);
mutex_unlock(&net_mutex);
out:
return rv;
}
EXPORT_SYMBOL_GPL(register_pernet_gen_subsys);
void unregister_pernet_gen_subsys(int id, struct pernet_operations *ops)
{
mutex_lock(&net_mutex);
unregister_pernet_operations(ops);
ida_remove(&net_generic_ids, id);
mutex_unlock(&net_mutex);
}
EXPORT_SYMBOL_GPL(unregister_pernet_gen_subsys);
/** /**
* register_pernet_device - register a network namespace device * register_pernet_device - register a network namespace device
* @ops: pernet operations structure for the subsystem * @ops: pernet operations structure for the subsystem
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment