aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Emelianov <xemul@openvz.org>2007-10-19 02:39:48 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-19 14:53:37 -0400
commitbaf8f0f82dd79e374bf6fa9e996393df2bae3c21 (patch)
tree2cf18de413871812527147cd8fbf32d1dbbe7bee
parenta05f7b15deb2903d9f0b5df33ddd4d186d5ecac1 (diff)
pid namespaces: dynamic kmem cache allocator for pid namespaces
Add kmem_cache to pid_namespace to allocate pids from. Since both implementations expand the struct pid to carry more numerical values each namespace should have separate cache to store pids of different sizes. Each kmem cache is name "pid_<NR>", where <NR> is the number of numerical ids on the pid. Different namespaces with same level of nesting will have same caches. This patch has two FIXMEs that are to be fixed after we reach the consensus about the struct pid itself. The first one is that the namespace to free the pid from in free_pid() must be taken from pid. Now the init_pid_ns is used. The second FIXME is about the cache allocation. When we do know how long the object will be then we'll have to calculate this size in create_pid_cachep. Right now the sizeof(struct pid) value is used. [akpm@linux-foundation.org: coding-style repair] Signed-off-by: Pavel Emelianov <xemul@openvz.org> Acked-by: Cedric Le Goater <clg@fr.ibm.com> Acked-by: Sukadev Bhattiprolu <sukadev@us.ibm.com> Cc: Kirill Korotaev <dev@openvz.org> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Herbert Poetzl <herbert@13thfloor.at> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/pid_namespace.h1
-rw-r--r--kernel/pid.c70
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
25extern struct pid_namespace init_pid_ns; 26extern 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)
33static struct hlist_head *pid_hash; 33static struct hlist_head *pid_hash;
34static int pidhash_shift; 34static int pidhash_shift;
35static struct kmem_cache *pid_cachep;
36struct pid init_struct_pid = INIT_STRUCT_PID; 35struct pid init_struct_pid = INIT_STRUCT_PID;
37 36
38int pid_max = PID_MAX_DEFAULT; 37int pid_max = PID_MAX_DEFAULT;
@@ -176,11 +175,16 @@ static int next_pidmap(struct pid_namespace *pid_ns, int last)
176 175
177fastcall void put_pid(struct pid *pid) 176fastcall 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}
185EXPORT_SYMBOL_GPL(put_pid); 189EXPORT_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
232out_free: 238out_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}
366EXPORT_SYMBOL_GPL(find_get_pid); 372EXPORT_SYMBOL_GPL(find_get_pid);
367 373
374struct pid_cache {
375 int nr_ids;
376 char name[16];
377 struct kmem_cache *cachep;
378 struct list_head list;
379};
380
381static LIST_HEAD(pid_caches_lh);
382static 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
389static 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);
413out:
414 mutex_unlock(&pid_caches_mutex);
415 return pcache->cachep;
416
417err_cachep:
418 kfree(pcache);
419err_alloc:
420 mutex_unlock(&pid_caches_mutex);
421 return NULL;
422}
423
368struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old_ns) 424struct 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}