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: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ad1d967c88
commit
485ac57bc1
|
@ -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)
|
||||||
}
|
}
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue