diff options
-rw-r--r-- | include/linux/pid_namespace.h | 1 | ||||
-rw-r--r-- | kernel/pid.c | 70 |
2 files changed, 65 insertions, 6 deletions
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index ddb9a4c95968..c471c0c6e9ce 100644 --- a/include/linux/pid_namespace.h +++ b/include/linux/pid_namespace.h | |||
@@ -20,6 +20,7 @@ struct pid_namespace { | |||
20 | struct pidmap pidmap[PIDMAP_ENTRIES]; | 20 | struct pidmap pidmap[PIDMAP_ENTRIES]; |
21 | int last_pid; | 21 | int last_pid; |
22 | struct task_struct *child_reaper; | 22 | struct task_struct *child_reaper; |
23 | struct kmem_cache *pid_cachep; | ||
23 | }; | 24 | }; |
24 | 25 | ||
25 | extern struct pid_namespace init_pid_ns; | 26 | extern struct pid_namespace init_pid_ns; |
diff --git a/kernel/pid.c b/kernel/pid.c index c6e3f9ffff87..42de9af8c524 100644 --- a/kernel/pid.c +++ b/kernel/pid.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift) | 32 | #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift) |
33 | static struct hlist_head *pid_hash; | 33 | static struct hlist_head *pid_hash; |
34 | static int pidhash_shift; | 34 | static int pidhash_shift; |
35 | static struct kmem_cache *pid_cachep; | ||
36 | struct pid init_struct_pid = INIT_STRUCT_PID; | 35 | struct pid init_struct_pid = INIT_STRUCT_PID; |
37 | 36 | ||
38 | int pid_max = PID_MAX_DEFAULT; | 37 | int pid_max = PID_MAX_DEFAULT; |
@@ -176,11 +175,16 @@ static int next_pidmap(struct pid_namespace *pid_ns, int last) | |||
176 | 175 | ||
177 | fastcall void put_pid(struct pid *pid) | 176 | fastcall void put_pid(struct pid *pid) |
178 | { | 177 | { |
178 | struct pid_namespace *ns; | ||
179 | |||
179 | if (!pid) | 180 | if (!pid) |
180 | return; | 181 | return; |
182 | |||
183 | /* FIXME - this must be the namespace this pid lives in */ | ||
184 | ns = &init_pid_ns; | ||
181 | if ((atomic_read(&pid->count) == 1) || | 185 | if ((atomic_read(&pid->count) == 1) || |
182 | atomic_dec_and_test(&pid->count)) | 186 | atomic_dec_and_test(&pid->count)) |
183 | kmem_cache_free(pid_cachep, pid); | 187 | kmem_cache_free(ns->pid_cachep, pid); |
184 | } | 188 | } |
185 | EXPORT_SYMBOL_GPL(put_pid); | 189 | EXPORT_SYMBOL_GPL(put_pid); |
186 | 190 | ||
@@ -208,12 +212,14 @@ struct pid *alloc_pid(void) | |||
208 | struct pid *pid; | 212 | struct pid *pid; |
209 | enum pid_type type; | 213 | enum pid_type type; |
210 | int nr = -1; | 214 | int nr = -1; |
215 | struct pid_namespace *ns; | ||
211 | 216 | ||
212 | pid = kmem_cache_alloc(pid_cachep, GFP_KERNEL); | 217 | ns = current->nsproxy->pid_ns; |
218 | pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL); | ||
213 | if (!pid) | 219 | if (!pid) |
214 | goto out; | 220 | goto out; |
215 | 221 | ||
216 | nr = alloc_pidmap(current->nsproxy->pid_ns); | 222 | nr = alloc_pidmap(ns); |
217 | if (nr < 0) | 223 | if (nr < 0) |
218 | goto out_free; | 224 | goto out_free; |
219 | 225 | ||
@@ -230,7 +236,7 @@ out: | |||
230 | return pid; | 236 | return pid; |
231 | 237 | ||
232 | out_free: | 238 | out_free: |
233 | kmem_cache_free(pid_cachep, pid); | 239 | kmem_cache_free(ns->pid_cachep, pid); |
234 | pid = NULL; | 240 | pid = NULL; |
235 | goto out; | 241 | goto out; |
236 | } | 242 | } |
@@ -365,6 +371,56 @@ struct pid *find_ge_pid(int nr) | |||
365 | } | 371 | } |
366 | EXPORT_SYMBOL_GPL(find_get_pid); | 372 | EXPORT_SYMBOL_GPL(find_get_pid); |
367 | 373 | ||
374 | struct pid_cache { | ||
375 | int nr_ids; | ||
376 | char name[16]; | ||
377 | struct kmem_cache *cachep; | ||
378 | struct list_head list; | ||
379 | }; | ||
380 | |||
381 | static LIST_HEAD(pid_caches_lh); | ||
382 | static DEFINE_MUTEX(pid_caches_mutex); | ||
383 | |||
384 | /* | ||
385 | * creates the kmem cache to allocate pids from. | ||
386 | * @nr_ids: the number of numerical ids this pid will have to carry | ||
387 | */ | ||
388 | |||
389 | static struct kmem_cache *create_pid_cachep(int nr_ids) | ||
390 | { | ||
391 | struct pid_cache *pcache; | ||
392 | struct kmem_cache *cachep; | ||
393 | |||
394 | mutex_lock(&pid_caches_mutex); | ||
395 | list_for_each_entry (pcache, &pid_caches_lh, list) | ||
396 | if (pcache->nr_ids == nr_ids) | ||
397 | goto out; | ||
398 | |||
399 | pcache = kmalloc(sizeof(struct pid_cache), GFP_KERNEL); | ||
400 | if (pcache == NULL) | ||
401 | goto err_alloc; | ||
402 | |||
403 | snprintf(pcache->name, sizeof(pcache->name), "pid_%d", nr_ids); | ||
404 | cachep = kmem_cache_create(pcache->name, | ||
405 | /* FIXME add numerical ids here */ | ||
406 | sizeof(struct pid), 0, SLAB_HWCACHE_ALIGN, NULL); | ||
407 | if (cachep == NULL) | ||
408 | goto err_cachep; | ||
409 | |||
410 | pcache->nr_ids = nr_ids; | ||
411 | pcache->cachep = cachep; | ||
412 | list_add(&pcache->list, &pid_caches_lh); | ||
413 | out: | ||
414 | mutex_unlock(&pid_caches_mutex); | ||
415 | return pcache->cachep; | ||
416 | |||
417 | err_cachep: | ||
418 | kfree(pcache); | ||
419 | err_alloc: | ||
420 | mutex_unlock(&pid_caches_mutex); | ||
421 | return NULL; | ||
422 | } | ||
423 | |||
368 | struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old_ns) | 424 | struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old_ns) |
369 | { | 425 | { |
370 | BUG_ON(!old_ns); | 426 | BUG_ON(!old_ns); |
@@ -412,5 +468,7 @@ void __init pidmap_init(void) | |||
412 | set_bit(0, init_pid_ns.pidmap[0].page); | 468 | set_bit(0, init_pid_ns.pidmap[0].page); |
413 | atomic_dec(&init_pid_ns.pidmap[0].nr_free); | 469 | atomic_dec(&init_pid_ns.pidmap[0].nr_free); |
414 | 470 | ||
415 | pid_cachep = KMEM_CACHE(pid, SLAB_PANIC); | 471 | init_pid_ns.pid_cachep = create_pid_cachep(1); |
472 | if (init_pid_ns.pid_cachep == NULL) | ||
473 | panic("Can't create pid_1 cachep\n"); | ||
416 | } | 474 | } |