aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2007-10-19 02:40:05 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-19 14:53:39 -0400
commit8ef047aaaeb811247a5639c92e2f2ae1221a28dd (patch)
tree296a61f66daa8ac42b3d77a53d06a97eb71155c9 /kernel
parentfaacbfd3a6808bf87d8f353b42eceeaba2c78a47 (diff)
pid namespaces: make alloc_pid(), free_pid() and put_pid() work with struct upid
Each struct upid element of struct pid has to be initialized properly, i.e. its nr mst be allocated from appropriate pidmap and ns set to appropriate namespace. When allocating a new pid, we need to know the namespace this pid will live in, so the additional argument is added to alloc_pid(). On the other hand, the rest of the kernel still uses the pid->nr and pid->pid_chain fields, so these ones are still initialized, but this will be removed soon. Signed-off-by: Pavel Emelyanov <xemul@openvz.org> Cc: Oleg Nesterov <oleg@tv-sign.ru> Cc: Sukadev Bhattiprolu <sukadev@us.ibm.com> Cc: Paul Menage <menage@google.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/fork.c2
-rw-r--r--kernel/pid.c49
2 files changed, 35 insertions, 16 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index d2f4a420a5b9..984d259e172d 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1041,7 +1041,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1041 goto bad_fork_cleanup_put_domain; 1041 goto bad_fork_cleanup_put_domain;
1042 1042
1043 if (pid != &init_struct_pid) { 1043 if (pid != &init_struct_pid) {
1044 pid = alloc_pid(); 1044 pid = alloc_pid(task_active_pid_ns(p));
1045 if (!pid) 1045 if (!pid)
1046 goto bad_fork_put_binfmt_module; 1046 goto bad_fork_put_binfmt_module;
1047 } 1047 }
diff --git a/kernel/pid.c b/kernel/pid.c
index c7346fb801fc..8132a6ddfa10 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -29,7 +29,8 @@
29#include <linux/pid_namespace.h> 29#include <linux/pid_namespace.h>
30#include <linux/init_task.h> 30#include <linux/init_task.h>
31 31
32#define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift) 32#define pid_hashfn(nr, ns) \
33 hash_long((unsigned long)nr + (unsigned long)ns, pidhash_shift)
33static struct hlist_head *pid_hash; 34static struct hlist_head *pid_hash;
34static int pidhash_shift; 35static int pidhash_shift;
35struct pid init_struct_pid = INIT_STRUCT_PID; 36struct pid init_struct_pid = INIT_STRUCT_PID;
@@ -186,11 +187,13 @@ fastcall void put_pid(struct pid *pid)
186 if (!pid) 187 if (!pid)
187 return; 188 return;
188 189
189 /* FIXME - this must be the namespace this pid lives in */ 190 ns = pid->numbers[pid->level].ns;
190 ns = &init_pid_ns;
191 if ((atomic_read(&pid->count) == 1) || 191 if ((atomic_read(&pid->count) == 1) ||
192 atomic_dec_and_test(&pid->count)) 192 atomic_dec_and_test(&pid->count)) {
193 kmem_cache_free(ns->pid_cachep, pid); 193 kmem_cache_free(ns->pid_cachep, pid);
194 if (ns != &init_pid_ns)
195 put_pid_ns(ns);
196 }
194} 197}
195EXPORT_SYMBOL_GPL(put_pid); 198EXPORT_SYMBOL_GPL(put_pid);
196 199
@@ -203,45 +206,61 @@ static void delayed_put_pid(struct rcu_head *rhp)
203fastcall void free_pid(struct pid *pid) 206fastcall void free_pid(struct pid *pid)
204{ 207{
205 /* We can be called with write_lock_irq(&tasklist_lock) held */ 208 /* We can be called with write_lock_irq(&tasklist_lock) held */
209 int i;
206 unsigned long flags; 210 unsigned long flags;
207 211
208 spin_lock_irqsave(&pidmap_lock, flags); 212 spin_lock_irqsave(&pidmap_lock, flags);
209 hlist_del_rcu(&pid->pid_chain); 213 hlist_del_rcu(&pid->pid_chain);
210 spin_unlock_irqrestore(&pidmap_lock, flags); 214 spin_unlock_irqrestore(&pidmap_lock, flags);
211 215
212 free_pidmap(&init_pid_ns, pid->nr); 216 for (i = 0; i <= pid->level; i++)
217 free_pidmap(pid->numbers[i].ns, pid->numbers[i].nr);
218
213 call_rcu(&pid->rcu, delayed_put_pid); 219 call_rcu(&pid->rcu, delayed_put_pid);
214} 220}
215 221
216struct pid *alloc_pid(void) 222struct pid *alloc_pid(struct pid_namespace *ns)
217{ 223{
218 struct pid *pid; 224 struct pid *pid;
219 enum pid_type type; 225 enum pid_type type;
220 int nr = -1; 226 int i, nr;
221 struct pid_namespace *ns; 227 struct pid_namespace *tmp;
222 228
223 ns = task_active_pid_ns(current);
224 pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL); 229 pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL);
225 if (!pid) 230 if (!pid)
226 goto out; 231 goto out;
227 232
228 nr = alloc_pidmap(ns); 233 tmp = ns;
229 if (nr < 0) 234 for (i = ns->level; i >= 0; i--) {
230 goto out_free; 235 nr = alloc_pidmap(tmp);
236 if (nr < 0)
237 goto out_free;
231 238
239 pid->numbers[i].nr = nr;
240 pid->numbers[i].ns = tmp;
241 tmp = tmp->parent;
242 }
243
244 if (ns != &init_pid_ns)
245 get_pid_ns(ns);
246
247 pid->level = ns->level;
248 pid->nr = pid->numbers[0].nr;
232 atomic_set(&pid->count, 1); 249 atomic_set(&pid->count, 1);
233 pid->nr = nr;
234 for (type = 0; type < PIDTYPE_MAX; ++type) 250 for (type = 0; type < PIDTYPE_MAX; ++type)
235 INIT_HLIST_HEAD(&pid->tasks[type]); 251 INIT_HLIST_HEAD(&pid->tasks[type]);
236 252
237 spin_lock_irq(&pidmap_lock); 253 spin_lock_irq(&pidmap_lock);
238 hlist_add_head_rcu(&pid->pid_chain, &pid_hash[pid_hashfn(pid->nr)]); 254 hlist_add_head_rcu(&pid->pid_chain, &pid_hash[pid_hashfn(pid->nr, ns)]);
239 spin_unlock_irq(&pidmap_lock); 255 spin_unlock_irq(&pidmap_lock);
240 256
241out: 257out:
242 return pid; 258 return pid;
243 259
244out_free: 260out_free:
261 for (i++; i <= ns->level; i++)
262 free_pidmap(pid->numbers[i].ns, pid->numbers[i].nr);
263
245 kmem_cache_free(ns->pid_cachep, pid); 264 kmem_cache_free(ns->pid_cachep, pid);
246 pid = NULL; 265 pid = NULL;
247 goto out; 266 goto out;
@@ -253,7 +272,7 @@ struct pid * fastcall find_pid(int nr)
253 struct pid *pid; 272 struct pid *pid;
254 273
255 hlist_for_each_entry_rcu(pid, elem, 274 hlist_for_each_entry_rcu(pid, elem,
256 &pid_hash[pid_hashfn(nr)], pid_chain) { 275 &pid_hash[pid_hashfn(nr, &init_pid_ns)], pid_chain) {
257 if (pid->nr == nr) 276 if (pid->nr == nr)
258 return pid; 277 return pid;
259 } 278 }