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