aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@gmail.com>2008-10-31 02:55:16 -0400
committerDavid S. Miller <davem@davemloft.net>2008-10-31 02:55:16 -0400
commit485ac57bc1238719b1508f91b0f9eeda4a3c84bb (patch)
treedaa4c6fde9255c7d3a2a1add5c8c78b418d5e81e
parentad1d967c88e349c7e822ad75dd3247a2a50d2ea3 (diff)
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>
-rw-r--r--include/net/net_namespace.h2
-rw-r--r--net/core/net_namespace.c32
2 files changed, 34 insertions, 0 deletions
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 708009be88b6..700c53a3c6fa 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -214,6 +214,8 @@ struct pernet_operations {
214 214
215extern int register_pernet_subsys(struct pernet_operations *); 215extern int register_pernet_subsys(struct pernet_operations *);
216extern void unregister_pernet_subsys(struct pernet_operations *); 216extern void unregister_pernet_subsys(struct pernet_operations *);
217extern int register_pernet_gen_subsys(int *id, struct pernet_operations *);
218extern void unregister_pernet_gen_subsys(int id, struct pernet_operations *);
217extern int register_pernet_device(struct pernet_operations *); 219extern int register_pernet_device(struct pernet_operations *);
218extern void unregister_pernet_device(struct pernet_operations *); 220extern void unregister_pernet_device(struct pernet_operations *);
219extern int register_pernet_gen_device(int *id, struct pernet_operations *); 221extern int register_pernet_gen_device(int *id, struct pernet_operations *);
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index f1d07b5c1e17..1895a4ca9c4f 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -325,6 +325,38 @@ void unregister_pernet_subsys(struct pernet_operations *module)
325} 325}
326EXPORT_SYMBOL_GPL(unregister_pernet_subsys); 326EXPORT_SYMBOL_GPL(unregister_pernet_subsys);
327 327
328int register_pernet_gen_subsys(int *id, struct pernet_operations *ops)
329{
330 int rv;
331
332 mutex_lock(&net_mutex);
333again:
334 rv = ida_get_new_above(&net_generic_ids, 1, id);
335 if (rv < 0) {
336 if (rv == -EAGAIN) {
337 ida_pre_get(&net_generic_ids, GFP_KERNEL);
338 goto again;
339 }
340 goto out;
341 }
342 rv = register_pernet_operations(first_device, ops);
343 if (rv < 0)
344 ida_remove(&net_generic_ids, *id);
345 mutex_unlock(&net_mutex);
346out:
347 return rv;
348}
349EXPORT_SYMBOL_GPL(register_pernet_gen_subsys);
350
351void unregister_pernet_gen_subsys(int id, struct pernet_operations *ops)
352{
353 mutex_lock(&net_mutex);
354 unregister_pernet_operations(ops);
355 ida_remove(&net_generic_ids, id);
356 mutex_unlock(&net_mutex);
357}
358EXPORT_SYMBOL_GPL(unregister_pernet_gen_subsys);
359
328/** 360/**
329 * register_pernet_device - register a network namespace device 361 * register_pernet_device - register a network namespace device
330 * @ops: pernet operations structure for the subsystem 362 * @ops: pernet operations structure for the subsystem