diff options
author | Pavel Emelyanov <xemul@openvz.org> | 2007-10-19 02:40:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-19 14:53:39 -0400 |
commit | 198fe21b0a17fe9c68cb519ecc566534b04f122b (patch) | |
tree | 690825669858d0f458fc137e42adf77cdf370ea4 | |
parent | 7af5729474b5b8ad385adadab78d6e723e7655a3 (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.c | 2 | ||||
-rw-r--r-- | include/linux/pid.h | 16 | ||||
-rw-r--r-- | include/linux/sched.h | 31 | ||||
-rw-r--r-- | kernel/pid.c | 43 |
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(); |
2334 | retry: | 2334 | retry: |
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)); | |||
99 | extern void FASTCALL(transfer_pid(struct task_struct *old, | 99 | extern 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 | ||
102 | struct pid_namespace; | ||
103 | extern 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 | */ |
106 | extern struct pid *FASTCALL(find_pid(int nr)); | 115 | extern 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 | */ |
111 | extern struct pid *find_get_pid(int nr); | 123 | extern struct pid *find_get_pid(int nr); |
112 | extern struct pid *find_ge_pid(int nr); | 124 | extern struct pid *find_ge_pid(int nr, struct pid_namespace *); |
113 | 125 | ||
114 | extern struct pid *alloc_pid(struct pid_namespace *ns); | 126 | extern struct pid *alloc_pid(struct pid_namespace *ns); |
115 | extern void FASTCALL(free_pid(struct pid *pid)); | 127 | extern 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 | ||
1515 | extern struct mm_struct init_mm; | 1515 | extern struct mm_struct init_mm; |
1516 | 1516 | ||
1517 | #define find_task_by_pid(nr) find_task_by_pid_type(PIDTYPE_PID, nr) | 1517 | extern struct pid_namespace init_pid_ns; |
1518 | extern 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 | |||
1536 | extern 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 | |||
1519 | extern void __set_special_pids(pid_t session, pid_t pgrp); | 1546 | extern 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 | }; |
74 | EXPORT_SYMBOL_GPL(init_pid_ns); | ||
74 | 75 | ||
75 | int is_global_init(struct task_struct *tsk) | 76 | int 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 | ||
257 | out: | 264 | out: |
@@ -266,19 +273,20 @@ out_free: | |||
266 | goto out; | 273 | goto out; |
267 | } | 274 | } |
268 | 275 | ||
269 | struct pid * fastcall find_pid(int nr) | 276 | struct 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 | } |
281 | EXPORT_SYMBOL_GPL(find_pid); | 289 | EXPORT_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 | */ |
341 | struct task_struct *find_task_by_pid_type(int type, int nr) | 349 | struct 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 | ||
346 | EXPORT_SYMBOL(find_task_by_pid_type); | 355 | EXPORT_SYMBOL(find_task_by_pid_type_ns); |
347 | 356 | ||
348 | struct pid *get_task_pid(struct task_struct *task, enum pid_type type) | 357 | struct 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 | */ |
397 | struct pid *find_ge_pid(int nr) | 406 | struct 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; |