aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2007-10-19 02:40:06 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-19 14:53:39 -0400
commit198fe21b0a17fe9c68cb519ecc566534b04f122b (patch)
tree690825669858d0f458fc137e42adf77cdf370ea4
parent7af5729474b5b8ad385adadab78d6e723e7655a3 (diff)
pid namespaces: helpers to find the task by its numerical ids
When searching the task by numerical id on may need to find it using global pid (as it is done now in kernel) or by its virtual id, e.g. when sending a signal to a task from one namespace the sender will specify the task's virtual id and we should find the task by this value. [akpm@linux-foundation.org: fix gfs2 linkage] 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>
-rw-r--r--fs/proc/base.c2
-rw-r--r--include/linux/pid.h16
-rw-r--r--include/linux/sched.h31
-rw-r--r--kernel/pid.c43
4 files changed, 70 insertions, 22 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 36983e7bb2c1..50e149e08d96 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2333,7 +2333,7 @@ static struct task_struct *next_tgid(unsigned int tgid)
2333 rcu_read_lock(); 2333 rcu_read_lock();
2334retry: 2334retry:
2335 task = NULL; 2335 task = NULL;
2336 pid = find_ge_pid(tgid); 2336 pid = find_ge_pid(tgid, &init_pid_ns);
2337 if (pid) { 2337 if (pid) {
2338 tgid = pid->nr + 1; 2338 tgid = pid->nr + 1;
2339 task = pid_task(pid, PIDTYPE_PID); 2339 task = pid_task(pid, PIDTYPE_PID);
diff --git a/include/linux/pid.h b/include/linux/pid.h
index c5fee61bfb4f..0dc940f4be46 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -99,17 +99,29 @@ extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type));
99extern void FASTCALL(transfer_pid(struct task_struct *old, 99extern void FASTCALL(transfer_pid(struct task_struct *old,
100 struct task_struct *new, enum pid_type)); 100 struct task_struct *new, enum pid_type));
101 101
102struct pid_namespace;
103extern struct pid_namespace init_pid_ns;
104
102/* 105/*
103 * look up a PID in the hash table. Must be called with the tasklist_lock 106 * look up a PID in the hash table. Must be called with the tasklist_lock
104 * or rcu_read_lock() held. 107 * or rcu_read_lock() held.
108 *
109 * find_pid_ns() finds the pid in the namespace specified
110 * find_pid() find the pid by its global id, i.e. in the init namespace
111 * find_vpid() finr the pid by its virtual id, i.e. in the current namespace
112 *
113 * see also find_task_by_pid() set in include/linux/sched.h
105 */ 114 */
106extern struct pid *FASTCALL(find_pid(int nr)); 115extern struct pid *FASTCALL(find_pid_ns(int nr, struct pid_namespace *ns));
116
117#define find_vpid(pid) find_pid_ns(pid, current->nsproxy->pid_ns)
118#define find_pid(pid) find_pid_ns(pid, &init_pid_ns)
107 119
108/* 120/*
109 * Lookup a PID in the hash table, and return with it's count elevated. 121 * Lookup a PID in the hash table, and return with it's count elevated.
110 */ 122 */
111extern struct pid *find_get_pid(int nr); 123extern struct pid *find_get_pid(int nr);
112extern struct pid *find_ge_pid(int nr); 124extern struct pid *find_ge_pid(int nr, struct pid_namespace *);
113 125
114extern struct pid *alloc_pid(struct pid_namespace *ns); 126extern struct pid *alloc_pid(struct pid_namespace *ns);
115extern void FASTCALL(free_pid(struct pid *pid)); 127extern void FASTCALL(free_pid(struct pid *pid));
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 77e8cad3b17a..511cc4549f58 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1514,8 +1514,35 @@ extern struct task_struct init_task;
1514 1514
1515extern struct mm_struct init_mm; 1515extern struct mm_struct init_mm;
1516 1516
1517#define find_task_by_pid(nr) find_task_by_pid_type(PIDTYPE_PID, nr) 1517extern struct pid_namespace init_pid_ns;
1518extern struct task_struct *find_task_by_pid_type(int type, int pid); 1518
1519/*
1520 * find a task by one of its numerical ids
1521 *
1522 * find_task_by_pid_type_ns():
1523 * it is the most generic call - it finds a task by all id,
1524 * type and namespace specified
1525 * find_task_by_pid_ns():
1526 * finds a task by its pid in the specified namespace
1527 * find_task_by_pid_type():
1528 * finds a task by its global id with the specified type, e.g.
1529 * by global session id
1530 * find_task_by_pid():
1531 * finds a task by its global pid
1532 *
1533 * see also find_pid() etc in include/linux/pid.h
1534 */
1535
1536extern struct task_struct *find_task_by_pid_type_ns(int type, int pid,
1537 struct pid_namespace *ns);
1538
1539#define find_task_by_pid_ns(nr, ns) \
1540 find_task_by_pid_type_ns(PIDTYPE_PID, nr, ns)
1541#define find_task_by_pid_type(type, nr) \
1542 find_task_by_pid_type_ns(type, nr, &init_pid_ns)
1543#define find_task_by_pid(nr) \
1544 find_task_by_pid_type(PIDTYPE_PID, nr)
1545
1519extern void __set_special_pids(pid_t session, pid_t pgrp); 1546extern void __set_special_pids(pid_t session, pid_t pgrp);
1520 1547
1521/* per-UID process charging. */ 1548/* per-UID process charging. */
diff --git a/kernel/pid.c b/kernel/pid.c
index 6eb14841b734..a2b4cbbdd63d 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -71,6 +71,7 @@ struct pid_namespace init_pid_ns = {
71 .level = 0, 71 .level = 0,
72 .child_reaper = &init_task, 72 .child_reaper = &init_task,
73}; 73};
74EXPORT_SYMBOL_GPL(init_pid_ns);
74 75
75int is_global_init(struct task_struct *tsk) 76int is_global_init(struct task_struct *tsk)
76{ 77{
@@ -210,7 +211,8 @@ fastcall void free_pid(struct pid *pid)
210 unsigned long flags; 211 unsigned long flags;
211 212
212 spin_lock_irqsave(&pidmap_lock, flags); 213 spin_lock_irqsave(&pidmap_lock, flags);
213 hlist_del_rcu(&pid->pid_chain); 214 for (i = 0; i <= pid->level; i++)
215 hlist_del_rcu(&pid->numbers[i].pid_chain);
214 spin_unlock_irqrestore(&pidmap_lock, flags); 216 spin_unlock_irqrestore(&pidmap_lock, flags);
215 217
216 for (i = 0; i <= pid->level; i++) 218 for (i = 0; i <= pid->level; i++)
@@ -225,6 +227,7 @@ struct pid *alloc_pid(struct pid_namespace *ns)
225 enum pid_type type; 227 enum pid_type type;
226 int i, nr; 228 int i, nr;
227 struct pid_namespace *tmp; 229 struct pid_namespace *tmp;
230 struct upid *upid;
228 231
229 pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL); 232 pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL);
230 if (!pid) 233 if (!pid)
@@ -251,7 +254,11 @@ struct pid *alloc_pid(struct pid_namespace *ns)
251 INIT_HLIST_HEAD(&pid->tasks[type]); 254 INIT_HLIST_HEAD(&pid->tasks[type]);
252 255
253 spin_lock_irq(&pidmap_lock); 256 spin_lock_irq(&pidmap_lock);
254 hlist_add_head_rcu(&pid->pid_chain, &pid_hash[pid_hashfn(pid->nr, ns)]); 257 for (i = ns->level; i >= 0; i--) {
258 upid = &pid->numbers[i];
259 hlist_add_head_rcu(&upid->pid_chain,
260 &pid_hash[pid_hashfn(upid->nr, upid->ns)]);
261 }
255 spin_unlock_irq(&pidmap_lock); 262 spin_unlock_irq(&pidmap_lock);
256 263
257out: 264out:
@@ -266,19 +273,20 @@ out_free:
266 goto out; 273 goto out;
267} 274}
268 275
269struct pid * fastcall find_pid(int nr) 276struct pid * fastcall find_pid_ns(int nr, struct pid_namespace *ns)
270{ 277{
271 struct hlist_node *elem; 278 struct hlist_node *elem;
272 struct pid *pid; 279 struct upid *pnr;
280
281 hlist_for_each_entry_rcu(pnr, elem,
282 &pid_hash[pid_hashfn(nr, ns)], pid_chain)
283 if (pnr->nr == nr && pnr->ns == ns)
284 return container_of(pnr, struct pid,
285 numbers[ns->level]);
273 286
274 hlist_for_each_entry_rcu(pid, elem,
275 &pid_hash[pid_hashfn(nr, &init_pid_ns)], pid_chain) {
276 if (pid->nr == nr)
277 return pid;
278 }
279 return NULL; 287 return NULL;
280} 288}
281EXPORT_SYMBOL_GPL(find_pid); 289EXPORT_SYMBOL_GPL(find_pid_ns);
282 290
283/* 291/*
284 * attach_pid() must be called with the tasklist_lock write-held. 292 * attach_pid() must be called with the tasklist_lock write-held.
@@ -338,12 +346,13 @@ struct task_struct * fastcall pid_task(struct pid *pid, enum pid_type type)
338/* 346/*
339 * Must be called under rcu_read_lock() or with tasklist_lock read-held. 347 * Must be called under rcu_read_lock() or with tasklist_lock read-held.
340 */ 348 */
341struct task_struct *find_task_by_pid_type(int type, int nr) 349struct task_struct *find_task_by_pid_type_ns(int type, int nr,
350 struct pid_namespace *ns)
342{ 351{
343 return pid_task(find_pid(nr), type); 352 return pid_task(find_pid_ns(nr, ns), type);
344} 353}
345 354
346EXPORT_SYMBOL(find_task_by_pid_type); 355EXPORT_SYMBOL(find_task_by_pid_type_ns);
347 356
348struct pid *get_task_pid(struct task_struct *task, enum pid_type type) 357struct pid *get_task_pid(struct task_struct *task, enum pid_type type)
349{ 358{
@@ -370,7 +379,7 @@ struct pid *find_get_pid(pid_t nr)
370 struct pid *pid; 379 struct pid *pid;
371 380
372 rcu_read_lock(); 381 rcu_read_lock();
373 pid = get_pid(find_pid(nr)); 382 pid = get_pid(find_vpid(nr));
374 rcu_read_unlock(); 383 rcu_read_unlock();
375 384
376 return pid; 385 return pid;
@@ -394,15 +403,15 @@ pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns)
394 * 403 *
395 * If there is a pid at nr this function is exactly the same as find_pid. 404 * If there is a pid at nr this function is exactly the same as find_pid.
396 */ 405 */
397struct pid *find_ge_pid(int nr) 406struct pid *find_ge_pid(int nr, struct pid_namespace *ns)
398{ 407{
399 struct pid *pid; 408 struct pid *pid;
400 409
401 do { 410 do {
402 pid = find_pid(nr); 411 pid = find_pid_ns(nr, ns);
403 if (pid) 412 if (pid)
404 break; 413 break;
405 nr = next_pidmap(task_active_pid_ns(current), nr); 414 nr = next_pidmap(ns, nr);
406 } while (nr > 0); 415 } while (nr > 0);
407 416
408 return pid; 417 return pid;