[NET]: Hide the net_ns kmem cache
[safe/jmp/linux-2.6] / net / core / net_namespace.c
1 #include <linux/workqueue.h>
2 #include <linux/rtnetlink.h>
3 #include <linux/cache.h>
4 #include <linux/slab.h>
5 #include <linux/list.h>
6 #include <linux/delay.h>
7 #include <linux/sched.h>
8 #include <net/net_namespace.h>
9
10 /*
11  *      Our network namespace constructor/destructor lists
12  */
13
14 static LIST_HEAD(pernet_list);
15 static struct list_head *first_device = &pernet_list;
16 static DEFINE_MUTEX(net_mutex);
17
18 LIST_HEAD(net_namespace_list);
19
20 struct net init_net;
21 EXPORT_SYMBOL_GPL(init_net);
22
23 /*
24  * setup_net runs the initializers for the network namespace object.
25  */
26 static __net_init int setup_net(struct net *net)
27 {
28         /* Must be called with net_mutex held */
29         struct pernet_operations *ops;
30         int error;
31
32         atomic_set(&net->count, 1);
33         atomic_set(&net->use_count, 0);
34
35         error = 0;
36         list_for_each_entry(ops, &pernet_list, list) {
37                 if (ops->init) {
38                         error = ops->init(net);
39                         if (error < 0)
40                                 goto out_undo;
41                 }
42         }
43 out:
44         return error;
45
46 out_undo:
47         /* Walk through the list backwards calling the exit functions
48          * for the pernet modules whose init functions did not fail.
49          */
50         list_for_each_entry_continue_reverse(ops, &pernet_list, list) {
51                 if (ops->exit)
52                         ops->exit(net);
53         }
54
55         rcu_barrier();
56         goto out;
57 }
58
59 #ifdef CONFIG_NET_NS
60 static struct kmem_cache *net_cachep;
61
62 static struct net *net_alloc(void)
63 {
64         return kmem_cache_zalloc(net_cachep, GFP_KERNEL);
65 }
66
67 struct net *copy_net_ns(unsigned long flags, struct net *old_net)
68 {
69         struct net *new_net = NULL;
70         int err;
71
72         get_net(old_net);
73
74         if (!(flags & CLONE_NEWNET))
75                 return old_net;
76
77         err = -ENOMEM;
78         new_net = net_alloc();
79         if (!new_net)
80                 goto out;
81
82         mutex_lock(&net_mutex);
83         err = setup_net(new_net);
84         if (err)
85                 goto out_unlock;
86
87         rtnl_lock();
88         list_add_tail(&new_net->list, &net_namespace_list);
89         rtnl_unlock();
90
91
92 out_unlock:
93         mutex_unlock(&net_mutex);
94 out:
95         put_net(old_net);
96         if (err) {
97                 net_free(new_net);
98                 new_net = ERR_PTR(err);
99         }
100         return new_net;
101 }
102
103 static void net_free(struct net *net)
104 {
105         if (!net)
106                 return;
107
108         if (unlikely(atomic_read(&net->use_count) != 0)) {
109                 printk(KERN_EMERG "network namespace not free! Usage: %d\n",
110                         atomic_read(&net->use_count));
111                 return;
112         }
113
114         kmem_cache_free(net_cachep, net);
115 }
116
117 static void cleanup_net(struct work_struct *work)
118 {
119         struct pernet_operations *ops;
120         struct net *net;
121
122         net = container_of(work, struct net, work);
123
124         mutex_lock(&net_mutex);
125
126         /* Don't let anyone else find us. */
127         rtnl_lock();
128         list_del(&net->list);
129         rtnl_unlock();
130
131         /* Run all of the network namespace exit methods */
132         list_for_each_entry_reverse(ops, &pernet_list, list) {
133                 if (ops->exit)
134                         ops->exit(net);
135         }
136
137         mutex_unlock(&net_mutex);
138
139         /* Ensure there are no outstanding rcu callbacks using this
140          * network namespace.
141          */
142         rcu_barrier();
143
144         /* Finally it is safe to free my network namespace structure */
145         net_free(net);
146 }
147
148 void __put_net(struct net *net)
149 {
150         /* Cleanup the network namespace in process context */
151         INIT_WORK(&net->work, cleanup_net);
152         schedule_work(&net->work);
153 }
154 EXPORT_SYMBOL_GPL(__put_net);
155
156 #else
157 struct net *copy_net_ns(unsigned long flags, struct net *old_net)
158 {
159         if (flags & CLONE_NEWNET)
160                 return ERR_PTR(-EINVAL);
161         return old_net;
162 }
163 #endif
164
165 static int __init net_ns_init(void)
166 {
167         int err;
168
169         printk(KERN_INFO "net_namespace: %zd bytes\n", sizeof(struct net));
170 #ifdef CONFIG_NET_NS
171         net_cachep = kmem_cache_create("net_namespace", sizeof(struct net),
172                                         SMP_CACHE_BYTES,
173                                         SLAB_PANIC, NULL);
174 #endif
175         mutex_lock(&net_mutex);
176         err = setup_net(&init_net);
177
178         rtnl_lock();
179         list_add_tail(&init_net.list, &net_namespace_list);
180         rtnl_unlock();
181
182         mutex_unlock(&net_mutex);
183         if (err)
184                 panic("Could not setup the initial network namespace");
185
186         return 0;
187 }
188
189 pure_initcall(net_ns_init);
190
191 static int register_pernet_operations(struct list_head *list,
192                                       struct pernet_operations *ops)
193 {
194         struct net *net, *undo_net;
195         int error;
196
197         list_add_tail(&ops->list, list);
198         if (ops->init) {
199                 for_each_net(net) {
200                         error = ops->init(net);
201                         if (error)
202                                 goto out_undo;
203                 }
204         }
205         return 0;
206
207 out_undo:
208         /* If I have an error cleanup all namespaces I initialized */
209         list_del(&ops->list);
210         if (ops->exit) {
211                 for_each_net(undo_net) {
212                         if (undo_net == net)
213                                 goto undone;
214                         ops->exit(undo_net);
215                 }
216         }
217 undone:
218         return error;
219 }
220
221 static void unregister_pernet_operations(struct pernet_operations *ops)
222 {
223         struct net *net;
224
225         list_del(&ops->list);
226         if (ops->exit)
227                 for_each_net(net)
228                         ops->exit(net);
229 }
230
231 /**
232  *      register_pernet_subsys - register a network namespace subsystem
233  *      @ops:  pernet operations structure for the subsystem
234  *
235  *      Register a subsystem which has init and exit functions
236  *      that are called when network namespaces are created and
237  *      destroyed respectively.
238  *
239  *      When registered all network namespace init functions are
240  *      called for every existing network namespace.  Allowing kernel
241  *      modules to have a race free view of the set of network namespaces.
242  *
243  *      When a new network namespace is created all of the init
244  *      methods are called in the order in which they were registered.
245  *
246  *      When a network namespace is destroyed all of the exit methods
247  *      are called in the reverse of the order with which they were
248  *      registered.
249  */
250 int register_pernet_subsys(struct pernet_operations *ops)
251 {
252         int error;
253         mutex_lock(&net_mutex);
254         error =  register_pernet_operations(first_device, ops);
255         mutex_unlock(&net_mutex);
256         return error;
257 }
258 EXPORT_SYMBOL_GPL(register_pernet_subsys);
259
260 /**
261  *      unregister_pernet_subsys - unregister a network namespace subsystem
262  *      @ops: pernet operations structure to manipulate
263  *
264  *      Remove the pernet operations structure from the list to be
265  *      used when network namespaces are created or destoryed.  In
266  *      addition run the exit method for all existing network
267  *      namespaces.
268  */
269 void unregister_pernet_subsys(struct pernet_operations *module)
270 {
271         mutex_lock(&net_mutex);
272         unregister_pernet_operations(module);
273         mutex_unlock(&net_mutex);
274 }
275 EXPORT_SYMBOL_GPL(unregister_pernet_subsys);
276
277 /**
278  *      register_pernet_device - register a network namespace device
279  *      @ops:  pernet operations structure for the subsystem
280  *
281  *      Register a device which has init and exit functions
282  *      that are called when network namespaces are created and
283  *      destroyed respectively.
284  *
285  *      When registered all network namespace init functions are
286  *      called for every existing network namespace.  Allowing kernel
287  *      modules to have a race free view of the set of network namespaces.
288  *
289  *      When a new network namespace is created all of the init
290  *      methods are called in the order in which they were registered.
291  *
292  *      When a network namespace is destroyed all of the exit methods
293  *      are called in the reverse of the order with which they were
294  *      registered.
295  */
296 int register_pernet_device(struct pernet_operations *ops)
297 {
298         int error;
299         mutex_lock(&net_mutex);
300         error = register_pernet_operations(&pernet_list, ops);
301         if (!error && (first_device == &pernet_list))
302                 first_device = &ops->list;
303         mutex_unlock(&net_mutex);
304         return error;
305 }
306 EXPORT_SYMBOL_GPL(register_pernet_device);
307
308 /**
309  *      unregister_pernet_device - unregister a network namespace netdevice
310  *      @ops: pernet operations structure to manipulate
311  *
312  *      Remove the pernet operations structure from the list to be
313  *      used when network namespaces are created or destoryed.  In
314  *      addition run the exit method for all existing network
315  *      namespaces.
316  */
317 void unregister_pernet_device(struct pernet_operations *ops)
318 {
319         mutex_lock(&net_mutex);
320         if (&ops->list == first_device)
321                 first_device = first_device->next;
322         unregister_pernet_operations(ops);
323         mutex_unlock(&net_mutex);
324 }
325 EXPORT_SYMBOL_GPL(unregister_pernet_device);